Source for java.awt.Window

   1: /* Window.java --
   2:    Copyright (C) 1999, 2000, 2002, 2003, 2004  Free Software Foundation
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package java.awt;
  40: 
  41: import java.awt.event.ComponentEvent;
  42: import java.awt.event.FocusEvent;
  43: import java.awt.event.WindowAdapter;
  44: import java.awt.event.WindowEvent;
  45: import java.awt.event.WindowFocusListener;
  46: import java.awt.event.WindowListener;
  47: import java.awt.event.WindowStateListener;
  48: import java.awt.image.BufferStrategy;
  49: import java.awt.peer.WindowPeer;
  50: import java.lang.ref.Reference;
  51: import java.lang.ref.WeakReference;
  52: import java.util.EventListener;
  53: import java.util.Iterator;
  54: import java.util.Locale;
  55: import java.util.ResourceBundle;
  56: import java.util.Vector;
  57: 
  58: import javax.accessibility.Accessible;
  59: import javax.accessibility.AccessibleContext;
  60: import javax.accessibility.AccessibleRole;
  61: import javax.accessibility.AccessibleState;
  62: import javax.accessibility.AccessibleStateSet;
  63: 
  64: /**
  65:  * This class represents a top-level window with no decorations.
  66:  *
  67:  * @author Aaron M. Renn (arenn@urbanophile.com)
  68:  * @author Warren Levy  (warrenl@cygnus.com)
  69:  */
  70: public class Window extends Container implements Accessible
  71: {
  72:   private static final long serialVersionUID = 4497834738069338734L;
  73: 
  74:   // Serialized fields, from Sun's serialization spec.
  75:   private String warningString = null;
  76:   private int windowSerializedDataVersion = 0; // FIXME
  77:   /** @since 1.2 */
  78:   // private FocusManager focusMgr;  // FIXME: what is this?  
  79:   /** @since 1.2 */
  80:   private int state = 0;
  81:   /** @since 1.4 */
  82:   private boolean focusableWindowState = true;
  83: 
  84:   // A list of other top-level windows owned by this window.
  85:   private transient Vector ownedWindows = new Vector();
  86: 
  87:   private transient WindowListener windowListener;
  88:   private transient WindowFocusListener windowFocusListener;
  89:   private transient WindowStateListener windowStateListener;
  90:   private transient GraphicsConfiguration graphicsConfiguration;
  91: 
  92:   private transient boolean shown;
  93: 
  94:   // This is package-private to avoid an accessor method.
  95:   transient Component windowFocusOwner;
  96:   
  97:   /*
  98:    * The number used to generate the name returned by getName.
  99:    */
 100:   private static transient long next_window_number;
 101: 
 102:   protected class AccessibleAWTWindow extends AccessibleAWTContainer
 103:   {
 104:     private static final long serialVersionUID = 4215068635060671780L;
 105: 
 106:     public AccessibleRole getAccessibleRole()
 107:     {
 108:       return AccessibleRole.WINDOW;
 109:     }
 110:     
 111:     public AccessibleStateSet getAccessibleStateSet()
 112:     {
 113:       AccessibleStateSet states = super.getAccessibleStateSet();
 114:       if (isActive())
 115:         states.add(AccessibleState.ACTIVE);
 116:       return states;
 117:     }
 118:   }
 119: 
 120:   /** 
 121:    * This (package access) constructor is used by subclasses that want
 122:    * to build windows that do not have parents.  Eg. toplevel
 123:    * application frames.  Subclasses cannot call super(null), since
 124:    * null is an illegal argument.
 125:    */
 126:   Window()
 127:   {
 128:     visible = false;
 129:     // Windows are the only Containers that default to being focus
 130:     // cycle roots.
 131:     focusCycleRoot = true;
 132:     setLayout(new BorderLayout());
 133: 
 134:     addWindowFocusListener (new WindowAdapter ()
 135:       {
 136:         public void windowGainedFocus (WindowEvent event)
 137:         {
 138:           if (windowFocusOwner != null)
 139:             {
 140:               // FIXME: move this section and the other similar
 141:               // sections in Component into a separate method.
 142:               EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
 143:               synchronized (eq)
 144:                 {
 145:                   KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
 146:                   Component currentFocusOwner = manager.getGlobalPermanentFocusOwner ();
 147:                   if (currentFocusOwner != null)
 148:                     {
 149:                       eq.postEvent (new FocusEvent (currentFocusOwner, FocusEvent.FOCUS_LOST,
 150:                                                     false, windowFocusOwner));
 151:                       eq.postEvent (new FocusEvent (windowFocusOwner, FocusEvent.FOCUS_GAINED,
 152:                                                     false, currentFocusOwner));
 153:                     }
 154:                   else
 155:                     eq.postEvent (new FocusEvent (windowFocusOwner, FocusEvent.FOCUS_GAINED, false));
 156:                 }
 157:             }
 158:         }
 159:       });
 160:     
 161:     GraphicsEnvironment g = GraphicsEnvironment.getLocalGraphicsEnvironment();
 162:     graphicsConfiguration = g.getDefaultScreenDevice().getDefaultConfiguration();
 163:   }
 164: 
 165:   Window(GraphicsConfiguration gc)
 166:   {
 167:     this();
 168:     graphicsConfiguration = gc;
 169:   }
 170: 
 171:   /**
 172:    * Initializes a new instance of <code>Window</code> with the specified
 173:    * parent.  The window will initially be invisible.
 174:    *
 175:    * @param owner The owning <code>Frame</code> of this window.
 176:    *
 177:    * @exception IllegalArgumentException If the owner's GraphicsConfiguration
 178:    * is not from a screen device, or if owner is null; this exception is always
 179:    * thrown when GraphicsEnvironment.isHeadless returns true.
 180:    */
 181:   public Window(Frame owner)
 182:   {
 183:     this (owner, owner.getGraphicsConfiguration ());
 184:   }
 185: 
 186:   /**
 187:    * Initializes a new instance of <code>Window</code> with the specified
 188:    * parent.  The window will initially be invisible.   
 189:    *
 190:    * @exception IllegalArgumentException If the owner's GraphicsConfiguration
 191:    * is not from a screen device, or if owner is null; this exception is always
 192:    * thrown when GraphicsEnvironment.isHeadless returns true.
 193:    *
 194:    * @since 1.2
 195:    */
 196:   public Window(Window owner)
 197:   {
 198:     this (owner, owner.getGraphicsConfiguration ());
 199:   }
 200:   
 201:   /**
 202:    * Initializes a new instance of <code>Window</code> with the specified
 203:    * parent.  The window will initially be invisible.   
 204:    *
 205:    * @exception IllegalArgumentException If owner is null or if gc is not from a
 206:    * screen device; this exception is always thrown when
 207:    * GraphicsEnvironment.isHeadless returns true.
 208:    *
 209:    * @since 1.3
 210:    */
 211:   public Window(Window owner, GraphicsConfiguration gc)
 212:   {
 213:     this ();
 214: 
 215:     synchronized (getTreeLock())
 216:       {
 217:     if (owner == null)
 218:       throw new IllegalArgumentException ("owner must not be null");
 219: 
 220:     parent = owner;
 221:         owner.ownedWindows.add(new WeakReference(this));
 222:       }
 223: 
 224:     // FIXME: make this text visible in the window.
 225:     SecurityManager s = System.getSecurityManager();
 226:     if (s != null && ! s.checkTopLevelWindow(this))
 227:       warningString = System.getProperty("awt.appletWarning");
 228: 
 229:     if (gc != null
 230:         && gc.getDevice().getType() != GraphicsDevice.TYPE_RASTER_SCREEN)
 231:       throw new IllegalArgumentException ("gc must be from a screen device");
 232: 
 233:     if (gc == null)
 234:       graphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment()
 235:                                                  .getDefaultScreenDevice()
 236:                                                  .getDefaultConfiguration();
 237:     else
 238:       graphicsConfiguration = gc;
 239:   }
 240: 
 241:   GraphicsConfiguration getGraphicsConfigurationImpl()
 242:   {
 243:     if (graphicsConfiguration != null)
 244:     return graphicsConfiguration;
 245: 
 246:     return super.getGraphicsConfigurationImpl();
 247:   }
 248: 
 249:   /**
 250:    * Creates the native peer for this window.
 251:    */
 252:   public void addNotify()
 253:   {
 254:     if (peer == null)
 255:       peer = getToolkit().createWindow(this);
 256:     super.addNotify();
 257:   }
 258: 
 259:   /**
 260:    * Relays out this window's child components at their preferred size.
 261:    *
 262:    * @specnote pack() doesn't appear to be called internally by show(), so
 263:    *             we duplicate some of the functionality.
 264:    */
 265:   public void pack()
 266:   {
 267:     if (parent != null && !parent.isDisplayable())
 268:       parent.addNotify();
 269:     if (peer == null)
 270:       addNotify();
 271: 
 272:     setSize(getPreferredSize());
 273: 
 274:     validate();
 275:   }
 276: 
 277:   /**
 278:    * Shows on-screen this window and any of its owned windows for whom
 279:    * isVisible returns true.
 280:    */
 281:   public void show()
 282:   {
 283:     synchronized (getTreeLock())
 284:     {
 285:     if (parent != null && !parent.isDisplayable())
 286:       parent.addNotify();
 287:     if (peer == null)
 288:       addNotify();
 289: 
 290:     // Show visible owned windows.
 291:     Iterator e = ownedWindows.iterator();
 292:     while(e.hasNext())
 293:       {
 294:         Window w = (Window)(((Reference) e.next()).get());
 295:         if (w != null)
 296:           {
 297:         if (w.isVisible())
 298:           w.getPeer().setVisible(true);
 299:           }
 300:              else
 301:           // Remove null weak reference from ownedWindows.
 302:           // Unfortunately this can't be done in the Window's
 303:           // finalize method because there is no way to guarantee
 304:           // synchronous access to ownedWindows there.
 305:           e.remove();
 306:       }
 307:     validate();
 308:     super.show();
 309:     toFront();
 310: 
 311:     KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
 312:     manager.setGlobalFocusedWindow (this);
 313:     
 314:     if (!shown)
 315:       {
 316:         FocusTraversalPolicy policy = getFocusTraversalPolicy ();
 317:         Component initialFocusOwner = null;
 318: 
 319:         if (policy != null)
 320:           initialFocusOwner = policy.getInitialComponent (this);
 321: 
 322:         if (initialFocusOwner != null)
 323:           initialFocusOwner.requestFocusInWindow ();
 324: 
 325:         shown = true;
 326:       }
 327:     }
 328:   }
 329: 
 330:   public void hide()
 331:   {
 332:     // Hide visible owned windows.
 333:     synchronized (getTreeLock ())
 334:       {
 335:     Iterator e = ownedWindows.iterator();
 336:     while(e.hasNext())
 337:       {
 338:         Window w = (Window)(((Reference) e.next()).get());
 339:         if (w != null)
 340:           {
 341:         if (w.isVisible() && w.getPeer() != null)
 342:           w.getPeer().setVisible(false);
 343:           }
 344:              else
 345:           e.remove();
 346:       }
 347:       }
 348:     super.hide();
 349:   }
 350: 
 351:   /**
 352:    * Destroys any resources associated with this window.  This includes
 353:    * all components in the window and all owned top-level windows.
 354:    */
 355:   public void dispose()
 356:   {
 357:     hide();
 358: 
 359:     synchronized (getTreeLock ())
 360:       {
 361:     Iterator e = ownedWindows.iterator();
 362:     while(e.hasNext())
 363:       {
 364:         Window w = (Window)(((Reference) e.next()).get());
 365:         if (w != null)
 366:           w.dispose();
 367:         else
 368:           // Remove null weak reference from ownedWindows.
 369:           e.remove();
 370:       }
 371: 
 372:     for (int i = 0; i < ncomponents; ++i)
 373:       component[i].removeNotify();
 374:     this.removeNotify();
 375: 
 376:         // Post a WINDOW_CLOSED event.
 377:         WindowEvent we = new WindowEvent(this, WindowEvent.WINDOW_CLOSED);
 378:         getToolkit().getSystemEventQueue().postEvent(we);
 379:       }
 380:   }
 381: 
 382:   /**
 383:    * Sends this window to the back so that all other windows display in
 384:    * front of it.
 385:    */
 386:   public void toBack()
 387:   {
 388:     if (peer != null)
 389:       {
 390:     WindowPeer wp = (WindowPeer) peer;
 391:     wp.toBack();
 392:       }
 393:   }
 394: 
 395:   /**
 396:    * Brings this window to the front so that it displays in front of
 397:    * any other windows.
 398:    */
 399:   public void toFront()
 400:   {
 401:     if (peer != null)
 402:       {
 403:         WindowPeer wp = (WindowPeer) peer;
 404:         wp.toFront();
 405:       }
 406:   }
 407: 
 408:   /**
 409:    * Returns the toolkit used to create this window.
 410:    *
 411:    * @return The toolkit used to create this window.
 412:    *
 413:    * @specnote Unlike Component.getToolkit, this implementation always 
 414:    *           returns the value of Toolkit.getDefaultToolkit().
 415:    */
 416:   public Toolkit getToolkit()
 417:   {
 418:     return Toolkit.getDefaultToolkit();    
 419:   }
 420: 
 421:   /**
 422:    * Returns the warning string that will be displayed if this window is
 423:    * popped up by an unsecure applet or application.
 424:    *
 425:    * @return The unsecure window warning message.
 426:    */
 427:   public final String getWarningString()
 428:   {
 429:     return warningString;
 430:   }
 431: 
 432:   /**
 433:    * Returns the locale that this window is configured for.
 434:    *
 435:    * @return The locale this window is configured for.
 436:    */
 437:   public Locale getLocale()
 438:   {
 439:     return locale == null ? Locale.getDefault() : locale;
 440:   }
 441: 
 442:   /*
 443:   /** @since 1.2
 444:   public InputContext getInputContext()
 445:   {
 446:     // FIXME
 447:   }
 448:   */
 449: 
 450:   /**
 451:    * Sets the cursor for this window to the specifiec cursor.
 452:    *
 453:    * @param cursor The new cursor for this window.
 454:    */
 455:   public void setCursor(Cursor cursor)
 456:   {
 457:     super.setCursor(cursor);
 458:   }
 459: 
 460:   public Window getOwner()
 461:   {
 462:     return (Window) parent;
 463:   }
 464: 
 465:   /** @since 1.2 */
 466:   public Window[] getOwnedWindows()
 467:   {
 468:     Window [] trimmedList;
 469:     synchronized (getTreeLock ())
 470:       {
 471:     // Windows with non-null weak references in ownedWindows.
 472:     Window [] validList = new Window [ownedWindows.size()];
 473: 
 474:     Iterator e = ownedWindows.iterator();
 475:     int numValid = 0;
 476:     while (e.hasNext())
 477:       {
 478:         Window w = (Window)(((Reference) e.next()).get());
 479:         if (w != null)
 480:           validList[numValid++] = w;
 481:         else
 482:           // Remove null weak reference from ownedWindows.
 483:           e.remove();
 484:       }
 485: 
 486:     if (numValid != validList.length)
 487:       {
 488:         trimmedList = new Window [numValid];
 489:         System.arraycopy (validList, 0, trimmedList, 0, numValid);
 490:       }
 491:     else
 492:       trimmedList = validList;
 493:       }
 494:     return trimmedList;
 495:   }
 496: 
 497:   /**
 498:    * Adds the specified listener to the list of <code>WindowListeners</code>
 499:    * that will receive events for this window.
 500:    *
 501:    * @param listener The <code>WindowListener</code> to add.
 502:    */
 503:   public synchronized void addWindowListener(WindowListener listener)
 504:   {
 505:     windowListener = AWTEventMulticaster.add(windowListener, listener);
 506:   }
 507: 
 508:   /**
 509:    * Removes the specified listener from the list of
 510:    * <code>WindowListeners</code> that will receive events for this window.
 511:    *
 512:    * @param listener The <code>WindowListener</code> to remove.
 513:    */
 514:   public synchronized void removeWindowListener(WindowListener listener)
 515:   {
 516:     windowListener = AWTEventMulticaster.remove(windowListener, listener);
 517:   }
 518: 
 519:   /**
 520:    * Returns an array of all the window listeners registered on this window.
 521:    *
 522:    * @since 1.4
 523:    */
 524:   public synchronized WindowListener[] getWindowListeners()
 525:   {
 526:     return (WindowListener[])
 527:       AWTEventMulticaster.getListeners(windowListener,
 528:                                        WindowListener.class);
 529:   }
 530: 
 531:   /**
 532:    * Returns an array of all the window focus listeners registered on this
 533:    * window.
 534:    *
 535:    * @since 1.4
 536:    */
 537:   public synchronized WindowFocusListener[] getWindowFocusListeners()
 538:   {
 539:     return (WindowFocusListener[])
 540:       AWTEventMulticaster.getListeners(windowFocusListener,
 541:                                        WindowFocusListener.class);
 542:   }
 543:   
 544:   /**
 545:    * Returns an array of all the window state listeners registered on this
 546:    * window.
 547:    *
 548:    * @since 1.4
 549:    */
 550:   public synchronized WindowStateListener[] getWindowStateListeners()
 551:   {
 552:     return (WindowStateListener[])
 553:       AWTEventMulticaster.getListeners(windowStateListener,
 554:                                        WindowStateListener.class);
 555:   }
 556: 
 557:   /**
 558:    * Adds the specified listener to this window.
 559:    */
 560:   public void addWindowFocusListener (WindowFocusListener wfl)
 561:   {
 562:     windowFocusListener = AWTEventMulticaster.add (windowFocusListener, wfl);
 563:   }
 564:   
 565:   /**
 566:    * Adds the specified listener to this window.
 567:    *
 568:    * @since 1.4
 569:    */
 570:   public void addWindowStateListener (WindowStateListener wsl)
 571:   {
 572:     windowStateListener = AWTEventMulticaster.add (windowStateListener, wsl);  
 573:   }
 574:   
 575:   /**
 576:    * Removes the specified listener from this window.
 577:    */
 578:   public void removeWindowFocusListener (WindowFocusListener wfl)
 579:   {
 580:     windowFocusListener = AWTEventMulticaster.remove (windowFocusListener, wfl);
 581:   }
 582:   
 583:   /**
 584:    * Removes the specified listener from this window.
 585:    *
 586:    * @since 1.4
 587:    */
 588:   public void removeWindowStateListener (WindowStateListener wsl)
 589:   {
 590:     windowStateListener = AWTEventMulticaster.remove (windowStateListener, wsl);
 591:   }
 592: 
 593:   /**
 594:    * Returns an array of all the objects currently registered as FooListeners
 595:    * upon this Window. FooListeners are registered using the addFooListener
 596:    * method.
 597:    *
 598:    * @exception ClassCastException If listenerType doesn't specify a class or
 599:    * interface that implements java.util.EventListener.
 600:    *
 601:    * @since 1.3
 602:    */
 603:   public EventListener[] getListeners(Class listenerType)
 604:   {
 605:     if (listenerType == WindowListener.class)
 606:       return getWindowListeners();
 607:     return super.getListeners(listenerType);
 608:   }
 609: 
 610:   void dispatchEventImpl(AWTEvent e)
 611:   {
 612:     // Make use of event id's in order to avoid multiple instanceof tests.
 613:     if (e.id <= WindowEvent.WINDOW_LAST 
 614:         && e.id >= WindowEvent.WINDOW_FIRST
 615:         && (windowListener != null
 616:         || windowFocusListener != null
 617:         || windowStateListener != null
 618:         || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0))
 619:       processEvent(e);
 620:     else if (e.id == ComponentEvent.COMPONENT_RESIZED)
 621:       validate ();
 622:     else
 623:       super.dispatchEventImpl(e);
 624:   }
 625: 
 626:   /**
 627:    * Processes the specified event for this window.  If the event is an
 628:    * instance of <code>WindowEvent</code>, then
 629:    * <code>processWindowEvent()</code> is called to process the event,
 630:    * otherwise the superclass version of this method is invoked.
 631:    *
 632:    * @param evt The event to process.
 633:    */
 634:   protected void processEvent(AWTEvent evt)
 635:   {
 636:     if (evt instanceof WindowEvent)
 637:       processWindowEvent((WindowEvent) evt);
 638:     else
 639:       super.processEvent(evt);
 640:   }
 641: 
 642:   /**
 643:    * Dispatches this event to any listeners that are listening for
 644:    * <code>WindowEvents</code> on this window.  This method only gets
 645:    * invoked if it is enabled via <code>enableEvents()</code> or if
 646:    * a listener has been added.
 647:    *
 648:    * @param evt The event to process.
 649:    */
 650:   protected void processWindowEvent(WindowEvent evt)
 651:   {
 652:     int id = evt.getID();
 653: 
 654:     if (id == WindowEvent.WINDOW_GAINED_FOCUS
 655:     || id == WindowEvent.WINDOW_LOST_FOCUS)
 656:       processWindowFocusEvent (evt);
 657:     else if (id == WindowEvent.WINDOW_STATE_CHANGED)
 658:       processWindowStateEvent (evt);
 659:     else
 660:       {
 661:     if (windowListener != null)
 662:       {
 663:         switch (evt.getID())
 664:           {
 665:           case WindowEvent.WINDOW_ACTIVATED:
 666:         windowListener.windowActivated(evt);
 667:         break;
 668: 
 669:           case WindowEvent.WINDOW_CLOSED:
 670:         windowListener.windowClosed(evt);
 671:         break;
 672: 
 673:           case WindowEvent.WINDOW_CLOSING:
 674:         windowListener.windowClosing(evt);
 675:         break;
 676: 
 677:           case WindowEvent.WINDOW_DEACTIVATED:
 678:         windowListener.windowDeactivated(evt);
 679:         break;
 680: 
 681:           case WindowEvent.WINDOW_DEICONIFIED:
 682:         windowListener.windowDeiconified(evt);
 683:         break;
 684: 
 685:           case WindowEvent.WINDOW_ICONIFIED:
 686:         windowListener.windowIconified(evt);
 687:         break;
 688: 
 689:           case WindowEvent.WINDOW_OPENED:
 690:         windowListener.windowOpened(evt);
 691:         break;
 692: 
 693:           default:
 694:         break;
 695:           }
 696:       }
 697:       }
 698:   }
 699:   
 700:   /**
 701:    * Identifies if this window is active.  The active window is a Frame or
 702:    * Dialog that has focus or owns the active window.
 703:    *  
 704:    * @return true if active, else false.
 705:    * @since 1.4
 706:    */
 707:   public boolean isActive()
 708:   {
 709:     KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
 710:     return manager.getActiveWindow() == this;
 711:   }
 712: 
 713:   /**
 714:    * Identifies if this window is focused.  A window is focused if it is the
 715:    * focus owner or it contains the focus owner.
 716:    * 
 717:    * @return true if focused, else false.
 718:    * @since 1.4
 719:    */
 720:   public boolean isFocused()
 721:   {
 722:     KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
 723:     return manager.getFocusedWindow() == this;
 724:   }
 725:   
 726:   /**
 727:    * Returns the child window that has focus if this window is active.
 728:    * This method returns <code>null</code> if this window is not active
 729:    * or no children have focus.
 730:    *
 731:    * @return The component that has focus, or <code>null</code> if no
 732:    * component has focus.
 733:    */
 734:   public Component getFocusOwner ()
 735:   {
 736:     KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
 737: 
 738:     Window activeWindow = manager.getActiveWindow ();
 739: 
 740:     // The currently-focused Component belongs to the active Window.
 741:     if (activeWindow == this)
 742:       return manager.getFocusOwner ();
 743:     else
 744:       return null;
 745:   }
 746: 
 747:   /**
 748:    * Returns the child component of this window that would receive
 749:    * focus if this window were to become focused.  If the window
 750:    * already has the top-level focus, then this method returns the
 751:    * same component as getFocusOwner.  If no child component has
 752:    * requested focus within the window, then the initial focus owner
 753:    * is returned.  If this is a non-focusable window, this method
 754:    * returns null.
 755:    *
 756:    * @return the child component of this window that most recently had
 757:    * the focus, or <code>null</code>
 758:    * @since 1.4
 759:    */
 760:   public Component getMostRecentFocusOwner ()
 761:   {
 762:     return windowFocusOwner;
 763:   }
 764: 
 765:   /**
 766:    * Set the focus owner for this window.  This method is used to
 767:    * remember which component was focused when this window lost
 768:    * top-level focus, so that when it regains top-level focus the same
 769:    * child component can be refocused.
 770:    *
 771:    * @param windowFocusOwner the component in this window that owns
 772:    * the focus.
 773:    */
 774:   void setFocusOwner (Component windowFocusOwner)
 775:   {
 776:     this.windowFocusOwner = windowFocusOwner;
 777:   }
 778: 
 779:   /**
 780:    * Post a Java 1.0 event to the event queue.
 781:    *
 782:    * @param e The event to post.
 783:    *
 784:    * @deprecated
 785:    */
 786:   public boolean postEvent(Event e)
 787:   {
 788:     return handleEvent (e);
 789:   }
 790: 
 791:   /**
 792:    * Tests whether or not this window is visible on the screen.
 793:    *
 794:    * In contrast to the normal behaviour of Container, which is that
 795:    * a container is showing if its parent is visible and showing, a Window
 796:    * is even showing, if its parent (i.e. an invisible Frame) is not showing.
 797:    *
 798:    * @return <code>true</code> if this window is visible, <code>false</code>
 799:    * otherwise.
 800:    */
 801:   public boolean isShowing()
 802:   {
 803:     return isVisible();
 804:   }
 805: 
 806:   public void setLocationRelativeTo(Component c)
 807:   {
 808:     int x = 0;
 809:     int y = 0;
 810:     
 811:     if (c == null || !c.isShowing())
 812:       {
 813:         GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
 814:         Point center = ge.getCenterPoint();
 815:         x = center.x - (width / 2);
 816:         y = center.y - (height / 2);
 817:       }
 818:     else
 819:       {
 820:         int cWidth = c.getWidth();
 821:         int cHeight = c.getHeight();
 822:         Dimension screenSize = getToolkit().getScreenSize();
 823: 
 824:         x = c.getLocationOnScreen().x;
 825:         y = c.getLocationOnScreen().y;
 826:         
 827:         // If bottom of component is cut off, window placed
 828:         // on the left or the right side of component
 829:         if ((y + cHeight) > screenSize.height)
 830:           {
 831:             // If the right side of the component is closer to the center
 832:             if ((screenSize.width / 2 - x) <= 0)
 833:               {
 834:                 if ((x - width) >= 0)
 835:                   x -= width;
 836:                 else
 837:                   x = 0;
 838:               }
 839:             else
 840:               {
 841:                 if ((x + cWidth + width) <= screenSize.width)
 842:                   x += cWidth;
 843:                 else
 844:                   x = screenSize.width - width;
 845:               }
 846: 
 847:             y = screenSize.height - height;
 848:           }
 849:         else if (cWidth > width || cHeight > height)
 850:           {
 851:             // If right side of component is cut off
 852:             if ((x + width) > screenSize.width)
 853:               x = screenSize.width - width;
 854:             // If left side of component is cut off
 855:             else if (x < 0)
 856:               x = 0;
 857:             else
 858:               x += (cWidth - width) / 2;
 859:             
 860:             y += (cHeight - height) / 2;
 861:           }
 862:         else
 863:           {
 864:             // If right side of component is cut off
 865:             if ((x + width) > screenSize.width)
 866:               x = screenSize.width - width;
 867:             // If left side of component is cut off
 868:             else if (x < 0 || (x - (width - cWidth) / 2) < 0)
 869:               x = 0;
 870:             else
 871:               x -= (width - cWidth) / 2;
 872: 
 873:             if ((y - (height - cHeight) / 2) > 0)
 874:               y -= (height - cHeight) / 2;
 875:             else
 876:               y = 0;
 877:           }
 878:       }
 879: 
 880:     setLocation(x, y);
 881:   }
 882: 
 883:   /**
 884:    * A BltBufferStrategy for windows.
 885:    */
 886:   private class WindowBltBufferStrategy extends BltBufferStrategy
 887:   {
 888:     /**
 889:      * Creates a block transfer strategy for this window.
 890:      *
 891:      * @param numBuffers the number of buffers in this strategy
 892:      * @param accelerated true if the buffer should be accelerated,
 893:      * false otherwise
 894:      */
 895:     WindowBltBufferStrategy(int numBuffers, boolean accelerated)
 896:     {
 897:       super(numBuffers,
 898:         new BufferCapabilities(new ImageCapabilities(accelerated),
 899:                    new ImageCapabilities(accelerated),
 900:                    BufferCapabilities.FlipContents.COPIED));
 901:     }
 902:   }
 903: 
 904:   /**
 905:    * A FlipBufferStrategy for windows.
 906:    */
 907:   private class WindowFlipBufferStrategy extends FlipBufferStrategy
 908:   {
 909:     /**
 910:      * Creates a flip buffer strategy for this window.
 911:      *
 912:      * @param numBuffers the number of buffers in this strategy
 913:      *
 914:      * @throws AWTException if the requested number of buffers is not
 915:      * supported
 916:      */
 917:     WindowFlipBufferStrategy(int numBuffers)
 918:       throws AWTException
 919:     {
 920:       super(numBuffers,
 921:         new BufferCapabilities(new ImageCapabilities(true),
 922:                    new ImageCapabilities(true),
 923:                    BufferCapabilities.FlipContents.COPIED));
 924:     }
 925:   }
 926: 
 927:   /**
 928:    * Creates a buffering strategy that manages how this window is
 929:    * repainted.  This method attempts to create the optimum strategy
 930:    * based on the desired number of buffers.  Hardware or software
 931:    * acceleration may be used.
 932:    *
 933:    * createBufferStrategy attempts different levels of optimization,
 934:    * but guarantees that some strategy with the requested number of
 935:    * buffers will be created even if it is not optimal.  First it
 936:    * attempts to create a page flipping strategy, then an accelerated
 937:    * blitting strategy, then an unaccelerated blitting strategy.
 938:    *
 939:    * Calling this method causes any existing buffer strategy to be
 940:    * destroyed.
 941:    *
 942:    * @param numBuffers the number of buffers in this strategy
 943:    *
 944:    * @throws IllegalArgumentException if requested number of buffers
 945:    * is less than one
 946:    * @throws IllegalStateException if this window is not displayable
 947:    *
 948:    * @since 1.4
 949:    */
 950:   public void createBufferStrategy(int numBuffers)
 951:   {
 952:     if (numBuffers < 1)
 953:       throw new IllegalArgumentException("Window.createBufferStrategy: number"
 954:                      + " of buffers is less than one");
 955: 
 956:     if (!isDisplayable())
 957:       throw new IllegalStateException("Window.createBufferStrategy: window is"
 958:                       + " not displayable");
 959: 
 960:     BufferStrategy newStrategy = null;
 961: 
 962:     // try a flipping strategy
 963:     try
 964:       {
 965:     newStrategy = new WindowFlipBufferStrategy(numBuffers);
 966:       }
 967:     catch (AWTException e)
 968:       {
 969:       }
 970: 
 971:     // fall back to an accelerated blitting strategy
 972:     if (newStrategy == null)
 973:       newStrategy = new WindowBltBufferStrategy(numBuffers, true);
 974: 
 975:     bufferStrategy = newStrategy;
 976:   }
 977: 
 978:   /**
 979:    * Creates a buffering strategy that manages how this window is
 980:    * repainted.  This method attempts to create a strategy based on
 981:    * the specified capabilities and throws an exception if the
 982:    * requested strategy is not supported.
 983:    *
 984:    * Calling this method causes any existing buffer strategy to be
 985:    * destroyed.
 986:    *
 987:    * @param numBuffers the number of buffers in this strategy
 988:    * @param caps the requested buffering capabilities
 989:    *
 990:    * @throws AWTException if the requested capabilities are not
 991:    * supported
 992:    * @throws IllegalArgumentException if requested number of buffers
 993:    * is less than one or if caps is null
 994:    *
 995:    * @since 1.4
 996:    */
 997:   public void createBufferStrategy(int numBuffers, BufferCapabilities caps)
 998:     throws AWTException
 999:   {
1000:     if (numBuffers < 1)
1001:       throw new IllegalArgumentException("Window.createBufferStrategy: number"
1002:                      + " of buffers is less than one");
1003: 
1004:     if (caps == null)
1005:       throw new IllegalArgumentException("Window.createBufferStrategy:"
1006:                      + " capabilities object is null");
1007: 
1008:     // a flipping strategy was requested
1009:     if (caps.isPageFlipping())
1010:       bufferStrategy = new WindowFlipBufferStrategy(numBuffers);
1011:     else
1012:       bufferStrategy = new WindowBltBufferStrategy(numBuffers, true);
1013:   }
1014: 
1015:   /**
1016:    * Returns the buffer strategy used by the window.
1017:    *
1018:    * @return the buffer strategy.
1019:    * @since 1.4
1020:    */
1021:   public BufferStrategy getBufferStrategy()
1022:   {
1023:     return bufferStrategy;
1024:   }
1025: 
1026:   /**
1027:    * @since 1.2
1028:    *
1029:    * @deprecated
1030:    */
1031:   public void applyResourceBundle(ResourceBundle rb)
1032:   {
1033:     throw new Error ("Not implemented");
1034:   }
1035: 
1036:   /**
1037:    * @since 1.2
1038:    *
1039:    * @deprecated
1040:    */
1041:   public void applyResourceBundle(String rbName)
1042:   {
1043:     ResourceBundle rb = ResourceBundle.getBundle(rbName, Locale.getDefault(),
1044:       ClassLoader.getSystemClassLoader());
1045:     if (rb != null)
1046:       applyResourceBundle(rb);    
1047:   }
1048: 
1049:   /**
1050:    * Gets the AccessibleContext associated with this <code>Window</code>.
1051:    * The context is created, if necessary.
1052:    *
1053:    * @return the associated context
1054:    */
1055:   public AccessibleContext getAccessibleContext()
1056:   {
1057:     /* Create the context if this is the first request */
1058:     if (accessibleContext == null)
1059:       accessibleContext = new AccessibleAWTWindow();
1060:     return accessibleContext;
1061:   }
1062: 
1063:   /** 
1064:    * Get graphics configuration.  The implementation for Window will
1065:    * not ask any parent containers, since Window is a toplevel
1066:    * window and not actually embedded in the parent component.
1067:    */
1068:   public GraphicsConfiguration getGraphicsConfiguration()
1069:   {
1070:     if (graphicsConfiguration != null) return graphicsConfiguration;
1071:     if (peer != null) return peer.getGraphicsConfiguration();
1072:     return null;
1073:   }
1074: 
1075:   protected void processWindowFocusEvent(WindowEvent event)
1076:   {
1077:     if (windowFocusListener != null)
1078:       {
1079:         switch (event.getID ())
1080:           {
1081:           case WindowEvent.WINDOW_GAINED_FOCUS:
1082:             windowFocusListener.windowGainedFocus (event);
1083:             break;
1084:             
1085:           case WindowEvent.WINDOW_LOST_FOCUS:
1086:             windowFocusListener.windowLostFocus (event);
1087:             break;
1088:             
1089:           default:
1090:             break;
1091:           }
1092:       }
1093:   }
1094:   
1095:   /**
1096:    * @since 1.4
1097:    */
1098:   protected void processWindowStateEvent(WindowEvent event)
1099:   {
1100:     if (windowStateListener != null
1101:         && event.getID () == WindowEvent.WINDOW_STATE_CHANGED)
1102:       windowStateListener.windowStateChanged (event);
1103:   }
1104: 
1105:   /**
1106:    * Returns whether this <code>Window</code> can get the focus or not.
1107:    *
1108:    * @since 1.4
1109:    */
1110:   public final boolean isFocusableWindow ()
1111:   {
1112:     if (getFocusableWindowState () == false)
1113:       return false;
1114: 
1115:     if (this instanceof Dialog
1116:         || this instanceof Frame)
1117:       return true;
1118: 
1119:     // FIXME: Implement more possible cases for returning true.
1120: 
1121:     return false;
1122:   }
1123:   
1124:   /**
1125:    * Returns the value of the focusableWindowState property.
1126:    * 
1127:    * @since 1.4
1128:    */
1129:   public boolean getFocusableWindowState ()
1130:   {
1131:     return focusableWindowState;
1132:   }
1133: 
1134:   /**
1135:    * Sets the value of the focusableWindowState property.
1136:    * 
1137:    * @since 1.4
1138:    */
1139:   public void setFocusableWindowState (boolean focusableWindowState)
1140:   {
1141:     this.focusableWindowState = focusableWindowState;
1142:   }
1143: 
1144:   /**
1145:    * Generate a unique name for this window.
1146:    *
1147:    * @return A unique name for this window.
1148:    */
1149:   String generateName()
1150:   {
1151:     return "win" + getUniqueLong();
1152:   }
1153: 
1154:   private static synchronized long getUniqueLong()
1155:   {
1156:     return next_window_number++;
1157:   }
1158: }