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:     public AccessibleRole getAccessibleRole()
 105:     {
 106:       return AccessibleRole.WINDOW;
 107:     }
 108:     
 109:     public AccessibleStateSet getAccessibleStateSet()
 110:     {
 111:       AccessibleStateSet states = super.getAccessibleStateSet();
 112:       if (isActive())
 113:         states.add(AccessibleState.ACTIVE);
 114:       return states;
 115:     }
 116:   }
 117: 
 118:   /** 
 119:    * This (package access) constructor is used by subclasses that want
 120:    * to build windows that do not have parents.  Eg. toplevel
 121:    * application frames.  Subclasses cannot call super(null), since
 122:    * null is an illegal argument.
 123:    */
 124:   Window()
 125:   {
 126:     visible = false;
 127:     // Windows are the only Containers that default to being focus
 128:     // cycle roots.
 129:     focusCycleRoot = true;
 130:     setLayout(new BorderLayout());
 131: 
 132:     addWindowFocusListener (new WindowAdapter ()
 133:       {
 134:         public void windowGainedFocus (WindowEvent event)
 135:         {
 136:           if (windowFocusOwner != null)
 137:             {
 138:               // FIXME: move this section and the other similar
 139:               // sections in Component into a separate method.
 140:               EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
 141:               synchronized (eq)
 142:                 {
 143:                   KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
 144:                   Component currentFocusOwner = manager.getGlobalPermanentFocusOwner ();
 145:                   if (currentFocusOwner != null)
 146:                     {
 147:                       eq.postEvent (new FocusEvent (currentFocusOwner, FocusEvent.FOCUS_LOST,
 148:                                                     false, windowFocusOwner));
 149:                       eq.postEvent (new FocusEvent (windowFocusOwner, FocusEvent.FOCUS_GAINED,
 150:                                                     false, currentFocusOwner));
 151:                     }
 152:                   else
 153:                     eq.postEvent (new FocusEvent (windowFocusOwner, FocusEvent.FOCUS_GAINED, false));
 154:                 }
 155:             }
 156:         }
 157:       });
 158:   }
 159: 
 160:   Window(GraphicsConfiguration gc)
 161:   {
 162:     this();
 163:     graphicsConfiguration = gc;
 164:   }
 165: 
 166:   /**
 167:    * Initializes a new instance of <code>Window</code> with the specified
 168:    * parent.  The window will initially be invisible.
 169:    *
 170:    * @param owner The owning <code>Frame</code> of this window.
 171:    *
 172:    * @exception IllegalArgumentException If the owner's GraphicsConfiguration
 173:    * is not from a screen device, or if owner is null; this exception is always
 174:    * thrown when GraphicsEnvironment.isHeadless returns true.
 175:    */
 176:   public Window(Frame owner)
 177:   {
 178:     this (owner, owner.getGraphicsConfiguration ());
 179:   }
 180: 
 181:   /**
 182:    * Initializes a new instance of <code>Window</code> with the specified
 183:    * parent.  The window will initially be invisible.   
 184:    *
 185:    * @exception IllegalArgumentException If the owner's GraphicsConfiguration
 186:    * is not from a screen device, or if owner is null; this exception is always
 187:    * thrown when GraphicsEnvironment.isHeadless returns true.
 188:    *
 189:    * @since 1.2
 190:    */
 191:   public Window(Window owner)
 192:   {
 193:     this (owner, owner.getGraphicsConfiguration ());
 194:   }
 195:   
 196:   /**
 197:    * Initializes a new instance of <code>Window</code> with the specified
 198:    * parent.  The window will initially be invisible.   
 199:    *
 200:    * @exception IllegalArgumentException If owner is null or if gc is not from a
 201:    * screen device; this exception is always thrown when
 202:    * GraphicsEnvironment.isHeadless returns true.
 203:    *
 204:    * @since 1.3
 205:    */
 206:   public Window(Window owner, GraphicsConfiguration gc)
 207:   {
 208:     this ();
 209: 
 210:     synchronized (getTreeLock())
 211:       {
 212:     if (owner == null)
 213:       throw new IllegalArgumentException ("owner must not be null");
 214: 
 215:     parent = owner;
 216:         owner.ownedWindows.add(new WeakReference(this));
 217:       }
 218: 
 219:     // FIXME: make this text visible in the window.
 220:     SecurityManager s = System.getSecurityManager();
 221:     if (s != null && ! s.checkTopLevelWindow(this))
 222:       warningString = System.getProperty("awt.appletWarning");
 223: 
 224:     if (gc != null
 225:         && gc.getDevice().getType() != GraphicsDevice.TYPE_RASTER_SCREEN)
 226:       throw new IllegalArgumentException ("gc must be from a screen device");
 227: 
 228:     if (gc == null)
 229:       graphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment()
 230:                                                  .getDefaultScreenDevice()
 231:                                                  .getDefaultConfiguration();
 232:     else
 233:       graphicsConfiguration = gc;
 234:   }
 235: 
 236:   GraphicsConfiguration getGraphicsConfigurationImpl()
 237:   {
 238:     if (graphicsConfiguration != null)
 239:     return graphicsConfiguration;
 240: 
 241:     return super.getGraphicsConfigurationImpl();
 242:   }
 243: 
 244:   /**
 245:    * Creates the native peer for this window.
 246:    */
 247:   public void addNotify()
 248:   {
 249:     if (peer == null)
 250:       peer = getToolkit().createWindow(this);
 251:     super.addNotify();
 252:   }
 253: 
 254:   /**
 255:    * Relays out this window's child components at their preferred size.
 256:    *
 257:    * @specnote pack() doesn't appear to be called internally by show(), so
 258:    *             we duplicate some of the functionality.
 259:    */
 260:   public void pack()
 261:   {
 262:     if (parent != null && !parent.isDisplayable())
 263:       parent.addNotify();
 264:     if (peer == null)
 265:       addNotify();
 266: 
 267:     setSize(getPreferredSize());
 268: 
 269:     validate();
 270:   }
 271: 
 272:   /**
 273:    * Shows on-screen this window and any of its owned windows for whom
 274:    * isVisible returns true.
 275:    */
 276:   public void show()
 277:   {
 278:     if (parent != null && !parent.isDisplayable())
 279:       parent.addNotify();
 280:     if (peer == null)
 281:       addNotify();
 282: 
 283:     // Show visible owned windows.
 284:     synchronized (getTreeLock())
 285:       {
 286:     Iterator e = ownedWindows.iterator();
 287:     while(e.hasNext())
 288:       {
 289:         Window w = (Window)(((Reference) e.next()).get());
 290:         if (w != null)
 291:           {
 292:         if (w.isVisible())
 293:           w.getPeer().setVisible(true);
 294:           }
 295:              else
 296:           // Remove null weak reference from ownedWindows.
 297:           // Unfortunately this can't be done in the Window's
 298:           // finalize method because there is no way to guarantee
 299:           // synchronous access to ownedWindows there.
 300:           e.remove();
 301:       }
 302:       }
 303:     validate();
 304:     super.show();
 305:     toFront();
 306: 
 307:     KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
 308:     manager.setGlobalFocusedWindow (this);
 309: 
 310:     if (!shown)
 311:       {
 312:         FocusTraversalPolicy policy = getFocusTraversalPolicy ();
 313:         Component initialFocusOwner = null;
 314: 
 315:         if (policy != null)
 316:           initialFocusOwner = policy.getInitialComponent (this);
 317: 
 318:         if (initialFocusOwner != null)
 319:           initialFocusOwner.requestFocusInWindow ();
 320: 
 321:         shown = true;
 322:       }
 323:   }
 324: 
 325:   public void hide()
 326:   {
 327:     // Hide visible owned windows.
 328:     synchronized (getTreeLock ())
 329:       {
 330:     Iterator e = ownedWindows.iterator();
 331:     while(e.hasNext())
 332:       {
 333:         Window w = (Window)(((Reference) e.next()).get());
 334:         if (w != null)
 335:           {
 336:         if (w.isVisible() && w.getPeer() != null)
 337:           w.getPeer().setVisible(false);
 338:           }
 339:              else
 340:           e.remove();
 341:       }
 342:       }
 343:     super.hide();
 344:   }
 345: 
 346:   public boolean isDisplayable()
 347:   {
 348:     if (super.isDisplayable())
 349:       return true;
 350:     return peer != null;
 351:   }
 352: 
 353:   /**
 354:    * Destroys any resources associated with this window.  This includes
 355:    * all components in the window and all owned top-level windows.
 356:    */
 357:   public void dispose()
 358:   {
 359:     hide();
 360: 
 361:     synchronized (getTreeLock ())
 362:       {
 363:     Iterator e = ownedWindows.iterator();
 364:     while(e.hasNext())
 365:       {
 366:         Window w = (Window)(((Reference) e.next()).get());
 367:         if (w != null)
 368:           w.dispose();
 369:         else
 370:           // Remove null weak reference from ownedWindows.
 371:           e.remove();
 372:       }
 373: 
 374:     for (int i = 0; i < ncomponents; ++i)
 375:       component[i].removeNotify();
 376:     this.removeNotify();
 377: 
 378:         // Post a WINDOW_CLOSED event.
 379:         WindowEvent we = new WindowEvent(this, WindowEvent.WINDOW_CLOSED);
 380:         getToolkit().getSystemEventQueue().postEvent(we);
 381:       }
 382:   }
 383: 
 384:   /**
 385:    * Sends this window to the back so that all other windows display in
 386:    * front of it.
 387:    */
 388:   public void toBack()
 389:   {
 390:     if (peer != null)
 391:       {
 392:     WindowPeer wp = (WindowPeer) peer;
 393:     wp.toBack();
 394:       }
 395:   }
 396: 
 397:   /**
 398:    * Brings this window to the front so that it displays in front of
 399:    * any other windows.
 400:    */
 401:   public void toFront()
 402:   {
 403:     if (peer != null)
 404:       {
 405:         WindowPeer wp = (WindowPeer) peer;
 406:         wp.toFront();
 407:       }
 408:   }
 409: 
 410:   /**
 411:    * Returns the toolkit used to create this window.
 412:    *
 413:    * @return The toolkit used to create this window.
 414:    *
 415:    * @specnote Unlike Component.getToolkit, this implementation always 
 416:    *           returns the value of Toolkit.getDefaultToolkit().
 417:    */
 418:   public Toolkit getToolkit()
 419:   {
 420:     return Toolkit.getDefaultToolkit();    
 421:   }
 422: 
 423:   /**
 424:    * Returns the warning string that will be displayed if this window is
 425:    * popped up by an unsecure applet or application.
 426:    *
 427:    * @return The unsecure window warning message.
 428:    */
 429:   public final String getWarningString()
 430:   {
 431:     return warningString;
 432:   }
 433: 
 434:   /**
 435:    * Returns the locale that this window is configured for.
 436:    *
 437:    * @return The locale this window is configured for.
 438:    */
 439:   public Locale getLocale()
 440:   {
 441:     return locale == null ? Locale.getDefault() : locale;
 442:   }
 443: 
 444:   /*
 445:   /** @since 1.2
 446:   public InputContext getInputContext()
 447:   {
 448:     // FIXME
 449:   }
 450:   */
 451: 
 452:   /**
 453:    * Sets the cursor for this window to the specifiec cursor.
 454:    *
 455:    * @param cursor The new cursor for this window.
 456:    */
 457:   public void setCursor(Cursor cursor)
 458:   {
 459:     super.setCursor(cursor);
 460:   }
 461: 
 462:   public Window getOwner()
 463:   {
 464:     return (Window) parent;
 465:   }
 466: 
 467:   /** @since 1.2 */
 468:   public Window[] getOwnedWindows()
 469:   {
 470:     Window [] trimmedList;
 471:     synchronized (getTreeLock ())
 472:       {
 473:     // Windows with non-null weak references in ownedWindows.
 474:     Window [] validList = new Window [ownedWindows.size()];
 475: 
 476:     Iterator e = ownedWindows.iterator();
 477:     int numValid = 0;
 478:     while (e.hasNext())
 479:       {
 480:         Window w = (Window)(((Reference) e.next()).get());
 481:         if (w != null)
 482:           validList[numValid++] = w;
 483:         else
 484:           // Remove null weak reference from ownedWindows.
 485:           e.remove();
 486:       }
 487: 
 488:     if (numValid != validList.length)
 489:       {
 490:         trimmedList = new Window [numValid];
 491:         System.arraycopy (validList, 0, trimmedList, 0, numValid);
 492:       }
 493:     else
 494:       trimmedList = validList;
 495:       }
 496:     return trimmedList;
 497:   }
 498: 
 499:   /**
 500:    * Adds the specified listener to the list of <code>WindowListeners</code>
 501:    * that will receive events for this window.
 502:    *
 503:    * @param listener The <code>WindowListener</code> to add.
 504:    */
 505:   public synchronized void addWindowListener(WindowListener listener)
 506:   {
 507:     windowListener = AWTEventMulticaster.add(windowListener, listener);
 508:   }
 509: 
 510:   /**
 511:    * Removes the specified listener from the list of
 512:    * <code>WindowListeners</code> that will receive events for this window.
 513:    *
 514:    * @param listener The <code>WindowListener</code> to remove.
 515:    */
 516:   public synchronized void removeWindowListener(WindowListener listener)
 517:   {
 518:     windowListener = AWTEventMulticaster.remove(windowListener, listener);
 519:   }
 520: 
 521:   /**
 522:    * Returns an array of all the window listeners registered on this window.
 523:    *
 524:    * @since 1.4
 525:    */
 526:   public synchronized WindowListener[] getWindowListeners()
 527:   {
 528:     return (WindowListener[])
 529:       AWTEventMulticaster.getListeners(windowListener,
 530:                                        WindowListener.class);
 531:   }
 532: 
 533:   /**
 534:    * Returns an array of all the window focus listeners registered on this
 535:    * window.
 536:    *
 537:    * @since 1.4
 538:    */
 539:   public synchronized WindowFocusListener[] getWindowFocusListeners()
 540:   {
 541:     return (WindowFocusListener[])
 542:       AWTEventMulticaster.getListeners(windowFocusListener,
 543:                                        WindowFocusListener.class);
 544:   }
 545:   
 546:   /**
 547:    * Returns an array of all the window state listeners registered on this
 548:    * window.
 549:    *
 550:    * @since 1.4
 551:    */
 552:   public synchronized WindowStateListener[] getWindowStateListeners()
 553:   {
 554:     return (WindowStateListener[])
 555:       AWTEventMulticaster.getListeners(windowStateListener,
 556:                                        WindowStateListener.class);
 557:   }
 558: 
 559:   /**
 560:    * Adds the specified listener to this window.
 561:    */
 562:   public void addWindowFocusListener (WindowFocusListener wfl)
 563:   {
 564:     windowFocusListener = AWTEventMulticaster.add (windowFocusListener, wfl);
 565:   }
 566:   
 567:   /**
 568:    * Adds the specified listener to this window.
 569:    *
 570:    * @since 1.4
 571:    */
 572:   public void addWindowStateListener (WindowStateListener wsl)
 573:   {
 574:     windowStateListener = AWTEventMulticaster.add (windowStateListener, wsl);  
 575:   }
 576:   
 577:   /**
 578:    * Removes the specified listener from this window.
 579:    */
 580:   public void removeWindowFocusListener (WindowFocusListener wfl)
 581:   {
 582:     windowFocusListener = AWTEventMulticaster.remove (windowFocusListener, wfl);
 583:   }
 584:   
 585:   /**
 586:    * Removes the specified listener from this window.
 587:    *
 588:    * @since 1.4
 589:    */
 590:   public void removeWindowStateListener (WindowStateListener wsl)
 591:   {
 592:     windowStateListener = AWTEventMulticaster.remove (windowStateListener, wsl);
 593:   }
 594: 
 595:   /**
 596:    * Returns an array of all the objects currently registered as FooListeners
 597:    * upon this Window. FooListeners are registered using the addFooListener
 598:    * method.
 599:    *
 600:    * @exception ClassCastException If listenerType doesn't specify a class or
 601:    * interface that implements java.util.EventListener.
 602:    *
 603:    * @since 1.3
 604:    */
 605:   public EventListener[] getListeners(Class listenerType)
 606:   {
 607:     if (listenerType == WindowListener.class)
 608:       return getWindowListeners();
 609:     return super.getListeners(listenerType);
 610:   }
 611: 
 612:   void dispatchEventImpl(AWTEvent e)
 613:   {
 614:     // Make use of event id's in order to avoid multiple instanceof tests.
 615:     if (e.id <= WindowEvent.WINDOW_LAST 
 616:         && e.id >= WindowEvent.WINDOW_FIRST
 617:         && (windowListener != null
 618:         || windowFocusListener != null
 619:         || windowStateListener != null
 620:         || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0))
 621:       processEvent(e);
 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 windowFocusOwner;
 745:   }
 746: 
 747:   /**
 748:    * Set the focus owner for this window.  This method is used to
 749:    * remember which component was focused when this window lost
 750:    * top-level focus, so that when it regains top-level focus the same
 751:    * child component can be refocused.
 752:    *
 753:    * @param windowFocusOwner the component in this window that owns
 754:    * the focus.
 755:    */
 756:   void setFocusOwner (Component windowFocusOwner)
 757:   {
 758:     this.windowFocusOwner = windowFocusOwner;
 759:   }
 760: 
 761:   /**
 762:    * Post a Java 1.0 event to the event queue.
 763:    *
 764:    * @param e The event to post.
 765:    *
 766:    * @deprecated
 767:    */
 768:   public boolean postEvent(Event e)
 769:   {
 770:     return handleEvent (e);
 771:   }
 772: 
 773:   /**
 774:    * Tests whether or not this window is visible on the screen.
 775:    *
 776:    * In contrast to the normal behaviour of Container, which is that
 777:    * a container is showing if its parent is visible and showing, a Window
 778:    * is even showing, if its parent (i.e. an invisible Frame) is not showing.
 779:    *
 780:    * @return <code>true</code> if this window is visible, <code>false</code>
 781:    * otherwise.
 782:    */
 783:   public boolean isShowing()
 784:   {
 785:     return isVisible();
 786:   }
 787: 
 788:   public void setLocationRelativeTo (Component c)
 789:   {
 790:     if (c == null || !c.isShowing ())
 791:       {
 792:         int x = 0;
 793:         int y = 0;
 794: 
 795:         GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment ();
 796:         Point center = ge.getCenterPoint ();
 797:         x = center.x - (width / 2);
 798:         y = center.y - (height / 2);
 799:         setLocation (x, y);
 800:       }
 801:     // FIXME: handle case where component is non-null.
 802:   }
 803: 
 804:   /**
 805:    * A BltBufferStrategy for windows.
 806:    */
 807:   private class WindowBltBufferStrategy extends BltBufferStrategy
 808:   {
 809:     /**
 810:      * Creates a block transfer strategy for this window.
 811:      *
 812:      * @param numBuffers the number of buffers in this strategy
 813:      * @param accelerated true if the buffer should be accelerated,
 814:      * false otherwise
 815:      */
 816:     WindowBltBufferStrategy(int numBuffers, boolean accelerated)
 817:     {
 818:       super(numBuffers,
 819:         new BufferCapabilities(new ImageCapabilities(accelerated),
 820:                    new ImageCapabilities(accelerated),
 821:                    BufferCapabilities.FlipContents.COPIED));
 822:     }
 823:   }
 824: 
 825:   /**
 826:    * A FlipBufferStrategy for windows.
 827:    */
 828:   private class WindowFlipBufferStrategy extends FlipBufferStrategy
 829:   {
 830:     /**
 831:      * Creates a flip buffer strategy for this window.
 832:      *
 833:      * @param numBuffers the number of buffers in this strategy
 834:      *
 835:      * @throws AWTException if the requested number of buffers is not
 836:      * supported
 837:      */
 838:     WindowFlipBufferStrategy(int numBuffers)
 839:       throws AWTException
 840:     {
 841:       super(numBuffers,
 842:         new BufferCapabilities(new ImageCapabilities(true),
 843:                    new ImageCapabilities(true),
 844:                    BufferCapabilities.FlipContents.COPIED));
 845:     }
 846:   }
 847: 
 848:   /**
 849:    * Creates a buffering strategy that manages how this window is
 850:    * repainted.  This method attempts to create the optimum strategy
 851:    * based on the desired number of buffers.  Hardware or software
 852:    * acceleration may be used.
 853:    *
 854:    * createBufferStrategy attempts different levels of optimization,
 855:    * but guarantees that some strategy with the requested number of
 856:    * buffers will be created even if it is not optimal.  First it
 857:    * attempts to create a page flipping strategy, then an accelerated
 858:    * blitting strategy, then an unaccelerated blitting strategy.
 859:    *
 860:    * Calling this method causes any existing buffer strategy to be
 861:    * destroyed.
 862:    *
 863:    * @param numBuffers the number of buffers in this strategy
 864:    *
 865:    * @throws IllegalArgumentException if requested number of buffers
 866:    * is less than one
 867:    * @throws IllegalStateException if this window is not displayable
 868:    *
 869:    * @since 1.4
 870:    */
 871:   public void createBufferStrategy(int numBuffers)
 872:   {
 873:     if (numBuffers < 1)
 874:       throw new IllegalArgumentException("Window.createBufferStrategy: number"
 875:                      + " of buffers is less than one");
 876: 
 877:     if (!isDisplayable())
 878:       throw new IllegalStateException("Window.createBufferStrategy: window is"
 879:                       + " not displayable");
 880: 
 881:     BufferStrategy newStrategy = null;
 882: 
 883:     // try a flipping strategy
 884:     try
 885:       {
 886:     newStrategy = new WindowFlipBufferStrategy(numBuffers);
 887:       }
 888:     catch (AWTException e)
 889:       {
 890:       }
 891: 
 892:     // fall back to an accelerated blitting strategy
 893:     if (newStrategy == null)
 894:       newStrategy = new WindowBltBufferStrategy(numBuffers, true);
 895: 
 896:     bufferStrategy = newStrategy;
 897:   }
 898: 
 899:   /**
 900:    * Creates a buffering strategy that manages how this window is
 901:    * repainted.  This method attempts to create a strategy based on
 902:    * the specified capabilities and throws an exception if the
 903:    * requested strategy is not supported.
 904:    *
 905:    * Calling this method causes any existing buffer strategy to be
 906:    * destroyed.
 907:    *
 908:    * @param numBuffers the number of buffers in this strategy
 909:    * @param caps the requested buffering capabilities
 910:    *
 911:    * @throws AWTException if the requested capabilities are not
 912:    * supported
 913:    * @throws IllegalArgumentException if requested number of buffers
 914:    * is less than one or if caps is null
 915:    *
 916:    * @since 1.4
 917:    */
 918:   public void createBufferStrategy(int numBuffers,
 919:                    BufferCapabilities caps)
 920:   {
 921:     if (numBuffers < 1)
 922:       throw new IllegalArgumentException("Window.createBufferStrategy: number"
 923:                      + " of buffers is less than one");
 924: 
 925:     if (caps == null)
 926:       throw new IllegalArgumentException("Window.createBufferStrategy:"
 927:                      + " capabilities object is null");
 928: 
 929:     // a flipping strategy was requested
 930:     if (caps.isPageFlipping())
 931:       {
 932:     try
 933:       {
 934:         bufferStrategy = new WindowFlipBufferStrategy(numBuffers);
 935:       }
 936:     catch (AWTException e)
 937:       {
 938:       }
 939:       }
 940:     else
 941:       bufferStrategy = new WindowBltBufferStrategy(numBuffers, true);
 942:   }
 943: 
 944:   /**
 945:    * Returns the buffer strategy used by the window.
 946:    *
 947:    * @return the buffer strategy.
 948:    * @since 1.4
 949:    */
 950:   public BufferStrategy getBufferStrategy()
 951:   {
 952:     return bufferStrategy;
 953:   }
 954: 
 955:   /**
 956:    * @since 1.2
 957:    *
 958:    * @deprecated
 959:    */
 960:   public void applyResourceBundle(ResourceBundle rb)
 961:   {
 962:     throw new Error ("Not implemented");
 963:   }
 964: 
 965:   /**
 966:    * @since 1.2
 967:    *
 968:    * @deprecated
 969:    */
 970:   public void applyResourceBundle(String rbName)
 971:   {
 972:     ResourceBundle rb = ResourceBundle.getBundle(rbName, Locale.getDefault(),
 973:       ClassLoader.getSystemClassLoader());
 974:     if (rb != null)
 975:       applyResourceBundle(rb);    
 976:   }
 977: 
 978:   /**
 979:    * Gets the AccessibleContext associated with this <code>Window</code>.
 980:    * The context is created, if necessary.
 981:    *
 982:    * @return the associated context
 983:    */
 984:   public AccessibleContext getAccessibleContext()
 985:   {
 986:     /* Create the context if this is the first request */
 987:     if (accessibleContext == null)
 988:       accessibleContext = new AccessibleAWTWindow();
 989:     return accessibleContext;
 990:   }
 991: 
 992:   /** 
 993:    * Get graphics configuration.  The implementation for Window will
 994:    * not ask any parent containers, since Window is a toplevel
 995:    * window and not actually embedded in the parent component.
 996:    */
 997:   public GraphicsConfiguration getGraphicsConfiguration()
 998:   {
 999:     if (graphicsConfiguration != null) return graphicsConfiguration;
1000:     if (peer != null) return peer.getGraphicsConfiguration();
1001:     return null;
1002:   }
1003: 
1004:   protected void processWindowFocusEvent(WindowEvent event)
1005:   {
1006:     if (windowFocusListener != null)
1007:       {
1008:         switch (event.getID ())
1009:           {
1010:           case WindowEvent.WINDOW_GAINED_FOCUS:
1011:             windowFocusListener.windowGainedFocus (event);
1012:             break;
1013:             
1014:           case WindowEvent.WINDOW_LOST_FOCUS:
1015:             windowFocusListener.windowLostFocus (event);
1016:             break;
1017:             
1018:           default:
1019:             break;
1020:           }
1021:       }
1022:   }
1023:   
1024:   /**
1025:    * @since 1.4
1026:    */
1027:   protected void processWindowStateEvent(WindowEvent event)
1028:   {
1029:     if (windowStateListener != null
1030:         && event.getID () == WindowEvent.WINDOW_STATE_CHANGED)
1031:       windowStateListener.windowStateChanged (event);
1032:   }
1033: 
1034:   /**
1035:    * Returns whether this <code>Window</code> can get the focus or not.
1036:    *
1037:    * @since 1.4
1038:    */
1039:   public final boolean isFocusableWindow ()
1040:   {
1041:     if (getFocusableWindowState () == false)
1042:       return false;
1043: 
1044:     if (this instanceof Dialog
1045:         || this instanceof Frame)
1046:       return true;
1047: 
1048:     // FIXME: Implement more possible cases for returning true.
1049: 
1050:     return false;
1051:   }
1052:   
1053:   /**
1054:    * Returns the value of the focusableWindowState property.
1055:    * 
1056:    * @since 1.4
1057:    */
1058:   public boolean getFocusableWindowState ()
1059:   {
1060:     return focusableWindowState;
1061:   }
1062: 
1063:   /**
1064:    * Sets the value of the focusableWindowState property.
1065:    * 
1066:    * @since 1.4
1067:    */
1068:   public void setFocusableWindowState (boolean focusableWindowState)
1069:   {
1070:     this.focusableWindowState = focusableWindowState;
1071:   }
1072: 
1073:   // setBoundsCallback is needed so that when a user moves a window,
1074:   // the Window's location can be updated without calling the peer's
1075:   // setBounds method.  When a user moves a window the peer window's
1076:   // location is updated automatically and the windowing system sends
1077:   // a message back to the application informing it of its updated
1078:   // dimensions.  We must update the AWT Window class with these new
1079:   // dimensions.  But we don't want to call the peer's setBounds
1080:   // method, because the peer's dimensions have already been updated.
1081:   // (Under X, having this method prevents Configure event loops when
1082:   // moving windows: Component.setBounds -> peer.setBounds ->
1083:   // postConfigureEvent -> Component.setBounds -> ...  In some cases
1084:   // Configure event loops cause windows to jitter back and forth
1085:   // continuously).
1086:   void setBoundsCallback (int x, int y, int w, int h)
1087:   {
1088:     if (this.x == x && this.y == y && width == w && height == h)
1089:       return;
1090:     invalidate();
1091:     boolean resized = width != w || height != h;
1092:     boolean moved = this.x != x || this.y != y;
1093:     this.x = x;
1094:     this.y = y;
1095:     width = w;
1096:     height = h;
1097:     if (resized && isShowing ())
1098:       {
1099:         ComponentEvent ce =
1100:           new ComponentEvent(this, ComponentEvent.COMPONENT_RESIZED);
1101:         getToolkit().getSystemEventQueue().postEvent(ce);
1102:       }
1103:     if (moved && isShowing ())
1104:       {
1105:         ComponentEvent ce =
1106:           new ComponentEvent(this, ComponentEvent.COMPONENT_MOVED);
1107:         getToolkit().getSystemEventQueue().postEvent(ce);
1108:       }
1109:   }
1110: 
1111:   /**
1112:    * Generate a unique name for this window.
1113:    *
1114:    * @return A unique name for this window.
1115:    */
1116:   String generateName()
1117:   {
1118:     return "win" + getUniqueLong();
1119:   }
1120: 
1121:   private static synchronized long getUniqueLong()
1122:   {
1123:     return next_window_number++;
1124:   }
1125: }