1 /*
   2  * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package java.awt;
  26 
  27 import java.awt.peer.FramePeer;
  28 import java.awt.event.*;
  29 import java.util.ArrayList;
  30 import java.util.Arrays;
  31 import java.util.List;
  32 import java.util.Vector;
  33 import java.io.Serializable;
  34 import java.io.ObjectOutputStream;
  35 import java.io.ObjectInputStream;
  36 import java.io.IOException;
  37 import sun.awt.AppContext;
  38 import sun.awt.SunToolkit;
  39 import sun.awt.AWTAccessor;
  40 import java.lang.ref.WeakReference;
  41 import javax.accessibility.*;
  42 
  43 /**
  44  * A <code>Frame</code> is a top-level window with a title and a border.
  45  * <p>
  46  * The size of the frame includes any area designated for the
  47  * border.  The dimensions of the border area may be obtained
  48  * using the <code>getInsets</code> method, however, since
  49  * these dimensions are platform-dependent, a valid insets
  50  * value cannot be obtained until the frame is made displayable
  51  * by either calling <code>pack</code> or <code>show</code>.
  52  * Since the border area is included in the overall size of the
  53  * frame, the border effectively obscures a portion of the frame,
  54  * constraining the area available for rendering and/or displaying
  55  * subcomponents to the rectangle which has an upper-left corner
  56  * location of <code>(insets.left, insets.top)</code>, and has a size of
  57  * <code>width - (insets.left + insets.right)</code> by
  58  * <code>height - (insets.top + insets.bottom)</code>.
  59  * <p>
  60  * The default layout for a frame is <code>BorderLayout</code>.
  61  * <p>
  62  * A frame may have its native decorations (i.e. <code>Frame</code>
  63  * and <code>Titlebar</code>) turned off
  64  * with <code>setUndecorated</code>. This can only be done while the frame
  65  * is not {@link Component#isDisplayable() displayable}.
  66  * <p>
  67  * In a multi-screen environment, you can create a <code>Frame</code>
  68  * on a different screen device by constructing the <code>Frame</code>
  69  * with {@link #Frame(GraphicsConfiguration)} or
  70  * {@link #Frame(String title, GraphicsConfiguration)}.  The
  71  * <code>GraphicsConfiguration</code> object is one of the
  72  * <code>GraphicsConfiguration</code> objects of the target screen
  73  * device.
  74  * <p>
  75  * In a virtual device multi-screen environment in which the desktop
  76  * area could span multiple physical screen devices, the bounds of all
  77  * configurations are relative to the virtual-coordinate system.  The
  78  * origin of the virtual-coordinate system is at the upper left-hand
  79  * corner of the primary physical screen.  Depending on the location
  80  * of the primary screen in the virtual device, negative coordinates
  81  * are possible, as shown in the following figure.
  82  * <p>
  83  * <img src="doc-files/MultiScreen.gif"
  84  * alt="Diagram of virtual device encompassing three physical screens and one primary physical screen. The primary physical screen
  85  * shows (0,0) coords while a different physical screen shows (-80,-100) coords."
  86  * ALIGN=center HSPACE=10 VSPACE=7>
  87  * <p>
  88  * In such an environment, when calling <code>setLocation</code>,
  89  * you must pass a virtual coordinate to this method.  Similarly,
  90  * calling <code>getLocationOnScreen</code> on a <code>Frame</code>
  91  * returns virtual device coordinates.  Call the <code>getBounds</code>
  92  * method of a <code>GraphicsConfiguration</code> to find its origin in
  93  * the virtual coordinate system.
  94  * <p>
  95  * The following code sets the
  96  * location of the <code>Frame</code> at (10, 10) relative
  97  * to the origin of the physical screen of the corresponding
  98  * <code>GraphicsConfiguration</code>.  If the bounds of the
  99  * <code>GraphicsConfiguration</code> is not taken into account, the
 100  * <code>Frame</code> location would be set at (10, 10) relative to the
 101  * virtual-coordinate system and would appear on the primary physical
 102  * screen, which might be different from the physical screen of the
 103  * specified <code>GraphicsConfiguration</code>.
 104  *
 105  * <pre>
 106  *      Frame f = new Frame(GraphicsConfiguration gc);
 107  *      Rectangle bounds = gc.getBounds();
 108  *      f.setLocation(10 + bounds.x, 10 + bounds.y);
 109  * </pre>
 110  *
 111  * <p>
 112  * Frames are capable of generating the following types of
 113  * <code>WindowEvent</code>s:
 114  * <ul>
 115  * <li><code>WINDOW_OPENED</code>
 116  * <li><code>WINDOW_CLOSING</code>:
 117  *     <br>If the program doesn't
 118  *     explicitly hide or dispose the window while processing
 119  *     this event, the window close operation is canceled.
 120  * <li><code>WINDOW_CLOSED</code>
 121  * <li><code>WINDOW_ICONIFIED</code>
 122  * <li><code>WINDOW_DEICONIFIED</code>
 123  * <li><code>WINDOW_ACTIVATED</code>
 124  * <li><code>WINDOW_DEACTIVATED</code>
 125  * <li><code>WINDOW_GAINED_FOCUS</code>
 126  * <li><code>WINDOW_LOST_FOCUS</code>
 127  * <li><code>WINDOW_STATE_CHANGED</code>
 128  * </ul>
 129  *
 130  * @author      Sami Shaio
 131  * @see WindowEvent
 132  * @see Window#addWindowListener
 133  * @since       JDK1.0
 134  */
 135 public class Frame extends Window implements MenuContainer {
 136 
 137     /* Note: These are being obsoleted;  programs should use the Cursor class
 138      * variables going forward. See Cursor and Component.setCursor.
 139      */
 140 
 141    /**
 142     * @deprecated   replaced by <code>Cursor.DEFAULT_CURSOR</code>.
 143     */
 144     @Deprecated
 145     public static final int     DEFAULT_CURSOR                  = Cursor.DEFAULT_CURSOR;
 146 
 147 
 148    /**
 149     * @deprecated   replaced by <code>Cursor.CROSSHAIR_CURSOR</code>.
 150     */
 151     @Deprecated
 152     public static final int     CROSSHAIR_CURSOR                = Cursor.CROSSHAIR_CURSOR;
 153 
 154    /**
 155     * @deprecated   replaced by <code>Cursor.TEXT_CURSOR</code>.
 156     */
 157     @Deprecated
 158     public static final int     TEXT_CURSOR                     = Cursor.TEXT_CURSOR;
 159 
 160    /**
 161     * @deprecated   replaced by <code>Cursor.WAIT_CURSOR</code>.
 162     */
 163     @Deprecated
 164     public static final int     WAIT_CURSOR                     = Cursor.WAIT_CURSOR;
 165 
 166    /**
 167     * @deprecated   replaced by <code>Cursor.SW_RESIZE_CURSOR</code>.
 168     */
 169     @Deprecated
 170     public static final int     SW_RESIZE_CURSOR                = Cursor.SW_RESIZE_CURSOR;
 171 
 172    /**
 173     * @deprecated   replaced by <code>Cursor.SE_RESIZE_CURSOR</code>.
 174     */
 175     @Deprecated
 176     public static final int     SE_RESIZE_CURSOR                = Cursor.SE_RESIZE_CURSOR;
 177 
 178    /**
 179     * @deprecated   replaced by <code>Cursor.NW_RESIZE_CURSOR</code>.
 180     */
 181     @Deprecated
 182     public static final int     NW_RESIZE_CURSOR                = Cursor.NW_RESIZE_CURSOR;
 183 
 184    /**
 185     * @deprecated   replaced by <code>Cursor.NE_RESIZE_CURSOR</code>.
 186     */
 187     @Deprecated
 188     public static final int     NE_RESIZE_CURSOR                = Cursor.NE_RESIZE_CURSOR;
 189 
 190    /**
 191     * @deprecated   replaced by <code>Cursor.N_RESIZE_CURSOR</code>.
 192     */
 193     @Deprecated
 194     public static final int     N_RESIZE_CURSOR                 = Cursor.N_RESIZE_CURSOR;
 195 
 196    /**
 197     * @deprecated   replaced by <code>Cursor.S_RESIZE_CURSOR</code>.
 198     */
 199     @Deprecated
 200     public static final int     S_RESIZE_CURSOR                 = Cursor.S_RESIZE_CURSOR;
 201 
 202    /**
 203     * @deprecated   replaced by <code>Cursor.W_RESIZE_CURSOR</code>.
 204     */
 205     @Deprecated
 206     public static final int     W_RESIZE_CURSOR                 = Cursor.W_RESIZE_CURSOR;
 207 
 208    /**
 209     * @deprecated   replaced by <code>Cursor.E_RESIZE_CURSOR</code>.
 210     */
 211     @Deprecated
 212     public static final int     E_RESIZE_CURSOR                 = Cursor.E_RESIZE_CURSOR;
 213 
 214    /**
 215     * @deprecated   replaced by <code>Cursor.HAND_CURSOR</code>.
 216     */
 217     @Deprecated
 218     public static final int     HAND_CURSOR                     = Cursor.HAND_CURSOR;
 219 
 220    /**
 221     * @deprecated   replaced by <code>Cursor.MOVE_CURSOR</code>.
 222     */
 223     @Deprecated
 224     public static final int     MOVE_CURSOR                     = Cursor.MOVE_CURSOR;
 225 
 226 
 227     /**
 228      * Frame is in the "normal" state.  This symbolic constant names a
 229      * frame state with all state bits cleared.
 230      * @see #setExtendedState(int)
 231      * @see #getExtendedState
 232      */
 233     public static final int NORMAL = 0;
 234 
 235     /**
 236      * This state bit indicates that frame is iconified.
 237      * @see #setExtendedState(int)
 238      * @see #getExtendedState
 239      */
 240     public static final int ICONIFIED = 1;
 241 
 242     /**
 243      * This state bit indicates that frame is maximized in the
 244      * horizontal direction.
 245      * @see #setExtendedState(int)
 246      * @see #getExtendedState
 247      * @since 1.4
 248      */
 249     public static final int MAXIMIZED_HORIZ = 2;
 250 
 251     /**
 252      * This state bit indicates that frame is maximized in the
 253      * vertical direction.
 254      * @see #setExtendedState(int)
 255      * @see #getExtendedState
 256      * @since 1.4
 257      */
 258     public static final int MAXIMIZED_VERT = 4;
 259 
 260     /**
 261      * This state bit mask indicates that frame is fully maximized
 262      * (that is both horizontally and vertically).  It is just a
 263      * convenience alias for
 264      * <code>MAXIMIZED_VERT&nbsp;|&nbsp;MAXIMIZED_HORIZ</code>.
 265      *
 266      * <p>Note that the correct test for frame being fully maximized is
 267      * <pre>
 268      *     (state & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH
 269      * </pre>
 270      *
 271      * <p>To test is frame is maximized in <em>some</em> direction use
 272      * <pre>
 273      *     (state & Frame.MAXIMIZED_BOTH) != 0
 274      * </pre>
 275      *
 276      * @see #setExtendedState(int)
 277      * @see #getExtendedState
 278      * @since 1.4
 279      */
 280     public static final int MAXIMIZED_BOTH = MAXIMIZED_VERT | MAXIMIZED_HORIZ;
 281 
 282     /**
 283      * Maximized bounds for this frame.
 284      * @see     #setMaximizedBounds(Rectangle)
 285      * @see     #getMaximizedBounds
 286      * @serial
 287      * @since 1.4
 288      */
 289     Rectangle maximizedBounds;
 290 
 291 
 292     /**
 293      * This is the title of the frame.  It can be changed
 294      * at any time.  <code>title</code> can be null and if
 295      * this is the case the <code>title</code> = "".
 296      *
 297      * @serial
 298      * @see #getTitle
 299      * @see #setTitle(String)
 300      */
 301     String      title = "Untitled";
 302 
 303     /**
 304      * The frames menubar.  If <code>menuBar</code> = null
 305      * the frame will not have a menubar.
 306      *
 307      * @serial
 308      * @see #getMenuBar
 309      * @see #setMenuBar(MenuBar)
 310      */
 311     MenuBar     menuBar;
 312 
 313     /**
 314      * This field indicates whether the frame is resizable.
 315      * This property can be changed at any time.
 316      * <code>resizable</code> will be true if the frame is
 317      * resizable, otherwise it will be false.
 318      *
 319      * @serial
 320      * @see #isResizable()
 321      */
 322     boolean     resizable = true;
 323 
 324     /**
 325      * This field indicates whether the frame is undecorated.
 326      * This property can only be changed while the frame is not displayable.
 327      * <code>undecorated</code> will be true if the frame is
 328      * undecorated, otherwise it will be false.
 329      *
 330      * @serial
 331      * @see #setUndecorated(boolean)
 332      * @see #isUndecorated()
 333      * @see Component#isDisplayable()
 334      * @since 1.4
 335      */
 336     boolean undecorated = false;
 337 
 338     /**
 339      * <code>mbManagement</code> is only used by the Motif implementation.
 340      *
 341      * @serial
 342      */
 343     boolean     mbManagement = false;   /* used only by the Motif impl. */
 344 
 345     // XXX: uwe: abuse old field for now
 346     // will need to take care of serialization
 347     private int state = NORMAL;
 348 
 349     /*
 350      * The Windows owned by the Frame.
 351      * Note: in 1.2 this has been superceded by Window.ownedWindowList
 352      *
 353      * @serial
 354      * @see java.awt.Window#ownedWindowList
 355      */
 356     Vector ownedWindows;
 357 
 358     private static final String base = "frame";
 359     private static int nameCounter = 0;
 360 
 361     /*
 362      * JDK 1.1 serialVersionUID
 363      */
 364      private static final long serialVersionUID = 2673458971256075116L;
 365 
 366     static {
 367         /* ensure that the necessary native libraries are loaded */
 368         Toolkit.loadLibraries();
 369         if (!GraphicsEnvironment.isHeadless()) {
 370             initIDs();
 371         }
 372     }
 373 
 374     /**
 375      * Constructs a new instance of <code>Frame</code> that is
 376      * initially invisible.  The title of the <code>Frame</code>
 377      * is empty.
 378      * @exception HeadlessException when
 379      *     <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code>
 380      * @see java.awt.GraphicsEnvironment#isHeadless()
 381      * @see Component#setSize
 382      * @see Component#setVisible(boolean)
 383      */
 384     public Frame() throws HeadlessException {
 385         this("");
 386     }
 387 
 388     /**
 389      * Constructs a new, initially invisible {@code Frame} with the
 390      * specified {@code GraphicsConfiguration}.
 391      *
 392      * @param gc the <code>GraphicsConfiguration</code>
 393      * of the target screen device. If <code>gc</code>
 394      * is <code>null</code>, the system default
 395      * <code>GraphicsConfiguration</code> is assumed.
 396      * @exception IllegalArgumentException if
 397      * <code>gc</code> is not from a screen device.
 398      * @exception HeadlessException when
 399      *     <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code>
 400      * @see java.awt.GraphicsEnvironment#isHeadless()
 401      * @since     1.3
 402      */
 403     public Frame(GraphicsConfiguration gc) {
 404         this("", gc);
 405     }
 406 
 407     /**
 408      * Constructs a new, initially invisible <code>Frame</code> object
 409      * with the specified title.
 410      * @param title the title to be displayed in the frame's border.
 411      *              A <code>null</code> value
 412      *              is treated as an empty string, "".
 413      * @exception HeadlessException when
 414      *     <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code>
 415      * @see java.awt.GraphicsEnvironment#isHeadless()
 416      * @see java.awt.Component#setSize
 417      * @see java.awt.Component#setVisible(boolean)
 418      * @see java.awt.GraphicsConfiguration#getBounds
 419      */
 420     public Frame(String title) throws HeadlessException {
 421         init(title, null);
 422     }
 423 
 424     /**
 425      * Constructs a new, initially invisible <code>Frame</code> object
 426      * with the specified title and a
 427      * <code>GraphicsConfiguration</code>.
 428      * @param title the title to be displayed in the frame's border.
 429      *              A <code>null</code> value
 430      *              is treated as an empty string, "".
 431      * @param gc the <code>GraphicsConfiguration</code>
 432      * of the target screen device.  If <code>gc</code> is
 433      * <code>null</code>, the system default
 434      * <code>GraphicsConfiguration</code> is assumed.
 435      * @exception IllegalArgumentException if <code>gc</code>
 436      * is not from a screen device.
 437      * @exception HeadlessException when
 438      *     <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code>
 439      * @see java.awt.GraphicsEnvironment#isHeadless()
 440      * @see java.awt.Component#setSize
 441      * @see java.awt.Component#setVisible(boolean)
 442      * @see java.awt.GraphicsConfiguration#getBounds
 443      * @since 1.3
 444      */
 445     public Frame(String title, GraphicsConfiguration gc) {
 446         super(gc);
 447         init(title, gc);
 448     }
 449 
 450     private void init(String title, GraphicsConfiguration gc) {
 451         this.title = title;
 452         SunToolkit.checkAndSetPolicy(this, false);
 453     }
 454 
 455     /**
 456      * Construct a name for this component.  Called by getName() when the
 457      * name is null.
 458      */
 459     String constructComponentName() {
 460         synchronized (Frame.class) {
 461             return base + nameCounter++;
 462         }
 463     }
 464 
 465     /**
 466      * Makes this Frame displayable by connecting it to
 467      * a native screen resource.  Making a frame displayable will
 468      * cause any of its children to be made displayable.
 469      * This method is called internally by the toolkit and should
 470      * not be called directly by programs.
 471      * @see Component#isDisplayable
 472      * @see #removeNotify
 473      */
 474     public void addNotify() {
 475         synchronized (getTreeLock()) {
 476             if (peer == null) {
 477                 peer = getToolkit().createFrame(this);
 478             }
 479             FramePeer p = (FramePeer)peer;
 480             MenuBar menuBar = this.menuBar;
 481             if (menuBar != null) {
 482                 mbManagement = true;
 483                 menuBar.addNotify();
 484                 p.setMenuBar(menuBar);
 485             }
 486             p.setMaximizedBounds(maximizedBounds);
 487             super.addNotify();
 488         }
 489     }
 490 
 491     /**
 492      * Gets the title of the frame.  The title is displayed in the
 493      * frame's border.
 494      * @return    the title of this frame, or an empty string ("")
 495      *                if this frame doesn't have a title.
 496      * @see       #setTitle(String)
 497      */
 498     public String getTitle() {
 499         return title;
 500     }
 501 
 502     /**
 503      * Sets the title for this frame to the specified string.
 504      * @param title the title to be displayed in the frame's border.
 505      *              A <code>null</code> value
 506      *              is treated as an empty string, "".
 507      * @see      #getTitle
 508      */
 509     public void setTitle(String title) {
 510         String oldTitle = this.title;
 511         if (title == null) {
 512             title = "";
 513         }
 514 
 515 
 516         synchronized(this) {
 517             this.title = title;
 518             FramePeer peer = (FramePeer)this.peer;
 519             if (peer != null) {
 520                 peer.setTitle(title);
 521             }
 522         }
 523         firePropertyChange("title", oldTitle, title);
 524     }
 525 
 526     /**
 527      * Returns the image to be displayed as the icon for this frame.
 528      * <p>
 529      * This method is obsolete and kept for backward compatibility
 530      * only. Use {@link Window#getIconImages Window.getIconImages()} instead.
 531      * <p>
 532      * If a list of several images was specified as a Window's icon,
 533      * this method will return the first item of the list.
 534      *
 535      * @return    the icon image for this frame, or <code>null</code>
 536      *                    if this frame doesn't have an icon image.
 537      * @see       #setIconImage(Image)
 538      * @see       Window#getIconImages()
 539      * @see       Window#setIconImages
 540      */
 541     public Image getIconImage() {
 542         java.util.List<Image> icons = this.icons;
 543         if (icons != null) {
 544             if (icons.size() > 0) {
 545                 return icons.get(0);
 546             }
 547         }
 548         return null;
 549     }
 550 
 551     /**
 552      * {@inheritDoc}
 553      */
 554     public void setIconImage(Image image) {
 555         super.setIconImage(image);
 556     }
 557 
 558     /**
 559      * Gets the menu bar for this frame.
 560      * @return    the menu bar for this frame, or <code>null</code>
 561      *                   if this frame doesn't have a menu bar.
 562      * @see       #setMenuBar(MenuBar)
 563      */
 564     public MenuBar getMenuBar() {
 565         return menuBar;
 566     }
 567 
 568     /**
 569      * Sets the menu bar for this frame to the specified menu bar.
 570      * @param     mb the menu bar being set.
 571      *            If this parameter is <code>null</code> then any
 572      *            existing menu bar on this frame is removed.
 573      * @see       #getMenuBar
 574      */
 575     public void setMenuBar(MenuBar mb) {
 576         synchronized (getTreeLock()) {
 577             if (menuBar == mb) {
 578                 return;
 579             }
 580             if ((mb != null) && (mb.parent != null)) {
 581                 mb.parent.remove(mb);
 582             }
 583             if (menuBar != null) {
 584                 remove(menuBar);
 585             }
 586             menuBar = mb;
 587             if (menuBar != null) {
 588                 menuBar.parent = this;
 589 
 590                 FramePeer peer = (FramePeer)this.peer;
 591                 if (peer != null) {
 592                     mbManagement = true;
 593                     menuBar.addNotify();
 594                     invalidateIfValid();
 595                     peer.setMenuBar(menuBar);
 596                 }
 597             }
 598         }
 599     }
 600 
 601     /**
 602      * Indicates whether this frame is resizable by the user.
 603      * By default, all frames are initially resizable.
 604      * @return    <code>true</code> if the user can resize this frame;
 605      *                        <code>false</code> otherwise.
 606      * @see       java.awt.Frame#setResizable(boolean)
 607      */
 608     public boolean isResizable() {
 609         return resizable;
 610     }
 611 
 612     /**
 613      * Sets whether this frame is resizable by the user.
 614      * @param    resizable   <code>true</code> if this frame is resizable;
 615      *                       <code>false</code> otherwise.
 616      * @see      java.awt.Frame#isResizable
 617      */
 618     public void setResizable(boolean resizable) {
 619         boolean oldResizable = this.resizable;
 620         boolean testvalid = false;
 621 
 622         synchronized (this) {
 623             this.resizable = resizable;
 624             FramePeer peer = (FramePeer)this.peer;
 625             if (peer != null) {
 626                 peer.setResizable(resizable);
 627                 testvalid = true;
 628             }
 629         }
 630 
 631         // On some platforms, changing the resizable state affects
 632         // the insets of the Frame. If we could, we'd call invalidate()
 633         // from the peer, but we need to guarantee that we're not holding
 634         // the Frame lock when we call invalidate().
 635         if (testvalid) {
 636             invalidateIfValid();
 637         }
 638         firePropertyChange("resizable", oldResizable, resizable);
 639     }
 640 
 641 
 642     /**
 643      * Sets the state of this frame (obsolete).
 644      * <p>
 645      * In older versions of JDK a frame state could only be NORMAL or
 646      * ICONIFIED.  Since JDK 1.4 set of supported frame states is
 647      * expanded and frame state is represented as a bitwise mask.
 648      * <p>
 649      * For compatibility with applications developed
 650      * earlier this method still accepts
 651      * {@code Frame.NORMAL} and
 652      * {@code Frame.ICONIFIED} only.  The iconic
 653      * state of the frame is only changed, other aspects
 654      * of frame state are not affected by this method. If
 655      * the state passed to this method is neither {@code
 656      * Frame.NORMAL} nor {@code Frame.ICONIFIED} the
 657      * method performs no actions at all.
 658      * <p>Note that if the state is not supported on a
 659      * given platform, neither the state nor the return
 660      * value of the {@link #getState} method will be
 661      * changed. The application may determine whether a
 662      * specific state is supported via the {@link
 663      * java.awt.Toolkit#isFrameStateSupported} method.
 664      * <p><b>If the frame is currently visible on the
 665      * screen</b> (the {@link #isShowing} method returns
 666      * {@code true}), the developer should examine the
 667      * return value of the  {@link
 668      * java.awt.event.WindowEvent#getNewState} method of
 669      * the {@code WindowEvent} received through the
 670      * {@link java.awt.event.WindowStateListener} to
 671      * determine that the state has actually been
 672      * changed.
 673      * <p><b>If the frame is not visible on the
 674      * screen</b>, the events may or may not be
 675      * generated.  In this case the developer may assume
 676      * that the state changes immediately after this
 677      * method returns.  Later, when the {@code
 678      * setVisible(true)} method is invoked, the frame
 679      * will attempt to apply this state. Receiving any
 680      * {@link
 681      * java.awt.event.WindowEvent#WINDOW_STATE_CHANGED}
 682      * events is not guaranteed in this case also.
 683      *
 684      * @param state either <code>Frame.NORMAL</code> or
 685      *     <code>Frame.ICONIFIED</code>.
 686      * @see #setExtendedState(int)
 687      * @see java.awt.Window#addWindowStateListener
 688      */
 689     public synchronized void setState(int state) {
 690         int current = getExtendedState();
 691         if (state == ICONIFIED && (current & ICONIFIED) == 0) {
 692             setExtendedState(current | ICONIFIED);
 693         }
 694         else if (state == NORMAL && (current & ICONIFIED) != 0) {
 695             setExtendedState(current & ~ICONIFIED);
 696         }
 697     }
 698 
 699     /**
 700      * Sets the state of this frame. The state is
 701      * represented as a bitwise mask.
 702      * <ul>
 703      * <li><code>NORMAL</code>
 704      * <br>Indicates that no state bits are set.
 705      * <li><code>ICONIFIED</code>
 706      * <li><code>MAXIMIZED_HORIZ</code>
 707      * <li><code>MAXIMIZED_VERT</code>
 708      * <li><code>MAXIMIZED_BOTH</code>
 709      * <br>Concatenates <code>MAXIMIZED_HORIZ</code>
 710      * and <code>MAXIMIZED_VERT</code>.
 711      * </ul>
 712      * <p>Note that if the state is not supported on a
 713      * given platform, neither the state nor the return
 714      * value of the {@link #getExtendedState} method will
 715      * be changed. The application may determine whether
 716      * a specific state is supported via the {@link
 717      * java.awt.Toolkit#isFrameStateSupported} method.
 718      * <p><b>If the frame is currently visible on the
 719      * screen</b> (the {@link #isShowing} method returns
 720      * {@code true}), the developer should examine the
 721      * return value of the {@link
 722      * java.awt.event.WindowEvent#getNewState} method of
 723      * the {@code WindowEvent} received through the
 724      * {@link java.awt.event.WindowStateListener} to
 725      * determine that the state has actually been
 726      * changed.
 727      * <p><b>If the frame is not visible on the
 728      * screen</b>, the events may or may not be
 729      * generated.  In this case the developer may assume
 730      * that the state changes immediately after this
 731      * method returns.  Later, when the {@code
 732      * setVisible(true)} method is invoked, the frame
 733      * will attempt to apply this state. Receiving any
 734      * {@link
 735      * java.awt.event.WindowEvent#WINDOW_STATE_CHANGED}
 736      * events is not guaranteed in this case also.
 737      *
 738      * @param state a bitwise mask of frame state constants
 739      * @since   1.4
 740      * @see java.awt.Window#addWindowStateListener
 741      */
 742     public void setExtendedState(int state) {
 743         if ( !isFrameStateSupported( state ) ) {
 744             return;
 745         }
 746         synchronized (getObjectLock()) {
 747             this.state = state;
 748         }
 749         // peer.setState must be called outside of object lock
 750         // synchronization block to avoid possible deadlock
 751         FramePeer peer = (FramePeer)this.peer;
 752         if (peer != null) {
 753             peer.setState(state);
 754         }
 755     }
 756     private boolean isFrameStateSupported(int state) {
 757         if( !getToolkit().isFrameStateSupported( state ) ) {
 758             // * Toolkit.isFrameStateSupported returns always false
 759             // on compound state even if all parts are supported;
 760             // * if part of state is not supported, state is not supported;
 761             // * MAXIMIZED_BOTH is not a compound state.
 762             if( ((state & ICONIFIED) != 0) &&
 763                 !getToolkit().isFrameStateSupported( ICONIFIED )) {
 764                 return false;
 765             }else {
 766                 state &= ~ICONIFIED;
 767             }
 768             return getToolkit().isFrameStateSupported( state );
 769         }
 770         return true;
 771     }
 772 
 773     /**
 774      * Gets the state of this frame (obsolete).
 775      * <p>
 776      * In older versions of JDK a frame state could only be NORMAL or
 777      * ICONIFIED.  Since JDK 1.4 set of supported frame states is
 778      * expanded and frame state is represented as a bitwise mask.
 779      * <p>
 780      * For compatibility with old programs this method still returns
 781      * <code>Frame.NORMAL</code> and <code>Frame.ICONIFIED</code> but
 782      * it only reports the iconic state of the frame, other aspects of
 783      * frame state are not reported by this method.
 784      *
 785      * @return  <code>Frame.NORMAL</code> or <code>Frame.ICONIFIED</code>.
 786      * @see     #setState(int)
 787      * @see     #getExtendedState
 788      */
 789     public synchronized int getState() {
 790         return (getExtendedState() & ICONIFIED) != 0 ? ICONIFIED : NORMAL;
 791     }
 792 
 793 
 794     /**
 795      * Gets the state of this frame. The state is
 796      * represented as a bitwise mask.
 797      * <ul>
 798      * <li><code>NORMAL</code>
 799      * <br>Indicates that no state bits are set.
 800      * <li><code>ICONIFIED</code>
 801      * <li><code>MAXIMIZED_HORIZ</code>
 802      * <li><code>MAXIMIZED_VERT</code>
 803      * <li><code>MAXIMIZED_BOTH</code>
 804      * <br>Concatenates <code>MAXIMIZED_HORIZ</code>
 805      * and <code>MAXIMIZED_VERT</code>.
 806      * </ul>
 807      *
 808      * @return  a bitwise mask of frame state constants
 809      * @see     #setExtendedState(int)
 810      * @since 1.4
 811      */
 812     public int getExtendedState() {
 813         synchronized (getObjectLock()) {
 814             return state;
 815         }
 816     }
 817 
 818     static {
 819         AWTAccessor.setFrameAccessor(
 820             new AWTAccessor.FrameAccessor() {
 821                 public void setExtendedState(Frame frame, int state) {
 822                     synchronized(frame.getObjectLock()) {
 823                         frame.state = state;
 824                     }
 825                 }
 826                 public int getExtendedState(Frame frame) {
 827                     synchronized(frame.getObjectLock()) {
 828                         return frame.state;
 829                     }
 830                 }
 831                 public Rectangle getMaximizedBounds(Frame frame) {
 832                     synchronized(frame.getObjectLock()) {
 833                         return frame.maximizedBounds;
 834                     }
 835                 }
 836             }
 837         );
 838     }
 839 
 840     /**
 841      * Sets the maximized bounds for this frame.
 842      * <p>
 843      * When a frame is in maximized state the system supplies some
 844      * defaults bounds.  This method allows some or all of those
 845      * system supplied values to be overridden.
 846      * <p>
 847      * If <code>bounds</code> is <code>null</code>, accept bounds
 848      * supplied by the system.  If non-<code>null</code> you can
 849      * override some of the system supplied values while accepting
 850      * others by setting those fields you want to accept from system
 851      * to <code>Integer.MAX_VALUE</code>.
 852      * <p>
 853      * Note, the given maximized bounds are used as a hint for the native
 854      * system, because the underlying platform may not support setting the
 855      * location and/or size of the maximized windows.  If that is the case, the
 856      * provided values do not affect the appearance of the frame in the
 857      * maximized state.
 858      *
 859      * @param bounds  bounds for the maximized state
 860      * @see #getMaximizedBounds()
 861      * @since 1.4
 862      */
 863     public void setMaximizedBounds(Rectangle bounds) {
 864         synchronized(getObjectLock()) {
 865             this.maximizedBounds = bounds;
 866         }
 867         FramePeer peer = (FramePeer)this.peer;
 868         if (peer != null) {
 869             peer.setMaximizedBounds(bounds);
 870         }
 871     }
 872 
 873     /**
 874      * Gets maximized bounds for this frame.
 875      * Some fields may contain <code>Integer.MAX_VALUE</code> to indicate
 876      * that system supplied values for this field must be used.
 877      *
 878      * @return  maximized bounds for this frame;  may be <code>null</code>
 879      * @see     #setMaximizedBounds(Rectangle)
 880      * @since   1.4
 881      */
 882     public Rectangle getMaximizedBounds() {
 883         synchronized(getObjectLock()) {
 884             return maximizedBounds;
 885         }
 886     }
 887 
 888 
 889     /**
 890      * Disables or enables decorations for this frame.
 891      * <p>
 892      * This method can only be called while the frame is not displayable. To
 893      * make this frame decorated, it must be opaque and have the default shape,
 894      * otherwise the {@code IllegalComponentStateException} will be thrown.
 895      * Refer to {@link Window#setShape}, {@link Window#setOpacity} and {@link
 896      * Window#setBackground} for details
 897      *
 898      * @param  undecorated {@code true} if no frame decorations are to be
 899      *         enabled; {@code false} if frame decorations are to be enabled
 900      *
 901      * @throws IllegalComponentStateException if the frame is displayable
 902      * @throws IllegalComponentStateException if {@code undecorated} is
 903      *      {@code false}, and this frame does not have the default shape
 904      * @throws IllegalComponentStateException if {@code undecorated} is
 905      *      {@code false}, and this frame opacity is less than {@code 1.0f}
 906      * @throws IllegalComponentStateException if {@code undecorated} is
 907      *      {@code false}, and the alpha value of this frame background
 908      *      color is less than {@code 1.0f}
 909      *
 910      * @see    #isUndecorated
 911      * @see    Component#isDisplayable
 912      * @see    Window#getShape
 913      * @see    Window#getOpacity
 914      * @see    Window#getBackground
 915      * @see    javax.swing.JFrame#setDefaultLookAndFeelDecorated(boolean)
 916      *
 917      * @since 1.4
 918      */
 919     public void setUndecorated(boolean undecorated) {
 920         /* Make sure we don't run in the middle of peer creation.*/
 921         synchronized (getTreeLock()) {
 922             if (isDisplayable()) {
 923                 throw new IllegalComponentStateException("The frame is displayable.");
 924             }
 925             if (!undecorated) {
 926                 if (getOpacity() < 1.0f) {
 927                     throw new IllegalComponentStateException("The frame is not opaque");
 928                 }
 929                 if (getShape() != null) {
 930                     throw new IllegalComponentStateException("The frame does not have a default shape");
 931                 }
 932                 Color bg = getBackground();
 933                 if ((bg != null) && (bg.getAlpha() < 255)) {
 934                     throw new IllegalComponentStateException("The frame background color is not opaque");
 935                 }
 936             }
 937             this.undecorated = undecorated;
 938         }
 939     }
 940 
 941     /**
 942      * Indicates whether this frame is undecorated.
 943      * By default, all frames are initially decorated.
 944      * @return    <code>true</code> if frame is undecorated;
 945      *                        <code>false</code> otherwise.
 946      * @see       java.awt.Frame#setUndecorated(boolean)
 947      * @since 1.4
 948      */
 949     public boolean isUndecorated() {
 950         return undecorated;
 951     }
 952 
 953     /**
 954      * {@inheritDoc}
 955      */
 956     @Override
 957     public void setOpacity(float opacity) {
 958         synchronized (getTreeLock()) {
 959             if ((opacity < 1.0f) && !isUndecorated()) {
 960                 throw new IllegalComponentStateException("The frame is decorated");
 961             }
 962             super.setOpacity(opacity);
 963         }
 964     }
 965 
 966     /**
 967      * {@inheritDoc}
 968      */
 969     @Override
 970     public void setShape(Shape shape) {
 971         synchronized (getTreeLock()) {
 972             if ((shape != null) && !isUndecorated()) {
 973                 throw new IllegalComponentStateException("The frame is decorated");
 974             }
 975             super.setShape(shape);
 976         }
 977     }
 978 
 979     /**
 980      * {@inheritDoc}
 981      */
 982     @Override
 983     public void setBackground(Color bgColor) {
 984         synchronized (getTreeLock()) {
 985             if ((bgColor != null) && (bgColor.getAlpha() < 255) && !isUndecorated()) {
 986                 throw new IllegalComponentStateException("The frame is decorated");
 987             }
 988             super.setBackground(bgColor);
 989         }
 990     }
 991 
 992     /**
 993      * Removes the specified menu bar from this frame.
 994      * @param    m   the menu component to remove.
 995      *           If <code>m</code> is <code>null</code>, then
 996      *           no action is taken
 997      */
 998     public void remove(MenuComponent m) {
 999         if (m == null) {
1000             return;
1001         }
1002         synchronized (getTreeLock()) {
1003             if (m == menuBar) {
1004                 menuBar = null;
1005                 FramePeer peer = (FramePeer)this.peer;
1006                 if (peer != null) {
1007                     mbManagement = true;
1008                     invalidateIfValid();
1009                     peer.setMenuBar(null);
1010                     m.removeNotify();
1011                 }
1012                 m.parent = null;
1013             } else {
1014                 super.remove(m);
1015             }
1016         }
1017     }
1018 
1019     /**
1020      * Makes this Frame undisplayable by removing its connection
1021      * to its native screen resource. Making a Frame undisplayable
1022      * will cause any of its children to be made undisplayable.
1023      * This method is called by the toolkit internally and should
1024      * not be called directly by programs.
1025      * @see Component#isDisplayable
1026      * @see #addNotify
1027      */
1028     public void removeNotify() {
1029         synchronized (getTreeLock()) {
1030             FramePeer peer = (FramePeer)this.peer;
1031             if (peer != null) {
1032                 // get the latest Frame state before disposing
1033                 getState();
1034 
1035                 if (menuBar != null) {
1036                     mbManagement = true;
1037                     peer.setMenuBar(null);
1038                     menuBar.removeNotify();
1039                 }
1040             }
1041             super.removeNotify();
1042         }
1043     }
1044 
1045     void postProcessKeyEvent(KeyEvent e) {
1046         if (menuBar != null && menuBar.handleShortcut(e)) {
1047             e.consume();
1048             return;
1049         }
1050         super.postProcessKeyEvent(e);
1051     }
1052 
1053     /**
1054      * Returns a string representing the state of this <code>Frame</code>.
1055      * This method is intended to be used only for debugging purposes, and the
1056      * content and format of the returned string may vary between
1057      * implementations. The returned string may be empty but may not be
1058      * <code>null</code>.
1059      *
1060      * @return the parameter string of this frame
1061      */
1062     protected String paramString() {
1063         String str = super.paramString();
1064         if (title != null) {
1065             str += ",title=" + title;
1066         }
1067         if (resizable) {
1068             str += ",resizable";
1069         }
1070         int state = getExtendedState();
1071         if (state == NORMAL) {
1072             str += ",normal";
1073         }
1074         else {
1075             if ((state & ICONIFIED) != 0) {
1076                 str += ",iconified";
1077             }
1078             if ((state & MAXIMIZED_BOTH) == MAXIMIZED_BOTH) {
1079                 str += ",maximized";
1080             }
1081             else if ((state & MAXIMIZED_HORIZ) != 0) {
1082                 str += ",maximized_horiz";
1083             }
1084             else if ((state & MAXIMIZED_VERT) != 0) {
1085                 str += ",maximized_vert";
1086             }
1087         }
1088         return str;
1089     }
1090 
1091     /**
1092      * @deprecated As of JDK version 1.1,
1093      * replaced by <code>Component.setCursor(Cursor)</code>.
1094      */
1095     @Deprecated
1096     public void setCursor(int cursorType) {
1097         if (cursorType < DEFAULT_CURSOR || cursorType > MOVE_CURSOR) {
1098             throw new IllegalArgumentException("illegal cursor type");
1099         }
1100         setCursor(Cursor.getPredefinedCursor(cursorType));
1101     }
1102 
1103     /**
1104      * @deprecated As of JDK version 1.1,
1105      * replaced by <code>Component.getCursor()</code>.
1106      */
1107     @Deprecated
1108     public int getCursorType() {
1109         return (getCursor().getType());
1110     }
1111 
1112     /**
1113      * Returns an array of all {@code Frame}s created by this application.
1114      * If called from an applet, the array includes only the {@code Frame}s
1115      * accessible by that applet.
1116      * <p>
1117      * <b>Warning:</b> this method may return system created frames, such
1118      * as a shared, hidden frame which is used by Swing. Applications
1119      * should not assume the existence of these frames, nor should an
1120      * application assume anything about these frames such as component
1121      * positions, <code>LayoutManager</code>s or serialization.
1122      * <p>
1123      * <b>Note</b>: To obtain a list of all ownerless windows, including
1124      * ownerless {@code Dialog}s (introduced in release 1.6), use {@link
1125      * Window#getOwnerlessWindows Window.getOwnerlessWindows}.
1126      *
1127      * @see Window#getWindows()
1128      * @see Window#getOwnerlessWindows
1129      *
1130      * @since 1.2
1131      */
1132     public static Frame[] getFrames() {
1133         Window[] allWindows = Window.getWindows();
1134 
1135         int frameCount = 0;
1136         for (Window w : allWindows) {
1137             if (w instanceof Frame) {
1138                 frameCount++;
1139             }
1140         }
1141 
1142         Frame[] frames = new Frame[frameCount];
1143         int c = 0;
1144         for (Window w : allWindows) {
1145             if (w instanceof Frame) {
1146                 frames[c++] = (Frame)w;
1147             }
1148         }
1149 
1150         return frames;
1151     }
1152 
1153     /* Serialization support.  If there's a MenuBar we restore
1154      * its (transient) parent field here.  Likewise for top level
1155      * windows that are "owned" by this frame.
1156      */
1157 
1158     /**
1159      * <code>Frame</code>'s Serialized Data Version.
1160      *
1161      * @serial
1162      */
1163     private int frameSerializedDataVersion = 1;
1164 
1165     /**
1166      * Writes default serializable fields to stream.  Writes
1167      * an optional serializable icon <code>Image</code>, which is
1168      * available as of 1.4.
1169      *
1170      * @param s the <code>ObjectOutputStream</code> to write
1171      * @serialData an optional icon <code>Image</code>
1172      * @see java.awt.Image
1173      * @see #getIconImage
1174      * @see #setIconImage(Image)
1175      * @see #readObject(ObjectInputStream)
1176      */
1177     private void writeObject(ObjectOutputStream s)
1178       throws IOException
1179     {
1180         s.defaultWriteObject();
1181         if (icons != null && icons.size() > 0) {
1182             Image icon1 = icons.get(0);
1183             if (icon1 instanceof Serializable) {
1184                 s.writeObject(icon1);
1185                 return;
1186             }
1187         }
1188         s.writeObject(null);
1189     }
1190 
1191     /**
1192      * Reads the <code>ObjectInputStream</code>.  Tries
1193      * to read an icon <code>Image</code>, which is optional
1194      * data available as of 1.4.  If an icon <code>Image</code>
1195      * is not available, but anything other than an EOF
1196      * is detected, an <code>OptionalDataException</code>
1197      * will be thrown.
1198      * Unrecognized keys or values will be ignored.
1199      *
1200      * @param s the <code>ObjectInputStream</code> to read
1201      * @exception java.io.OptionalDataException if an icon <code>Image</code>
1202      *   is not available, but anything other than an EOF
1203      *   is detected
1204      * @exception HeadlessException if
1205      *   <code>GraphicsEnvironment.isHeadless</code> returns
1206      *   <code>true</code>
1207      * @see java.awt.GraphicsEnvironment#isHeadless()
1208      * @see java.awt.Image
1209      * @see #getIconImage
1210      * @see #setIconImage(Image)
1211      * @see #writeObject(ObjectOutputStream)
1212      */
1213     private void readObject(ObjectInputStream s)
1214       throws ClassNotFoundException, IOException, HeadlessException
1215     {
1216       // HeadlessException is thrown by Window's readObject
1217       s.defaultReadObject();
1218       try {
1219           Image icon = (Image) s.readObject();
1220           if (icons == null) {
1221               icons = new ArrayList<Image>();
1222               icons.add(icon);
1223           }
1224       } catch (java.io.OptionalDataException e) {
1225           // pre-1.4 instances will not have this optional data.
1226           // 1.6 and later instances serialize icons in the Window class
1227           // e.eof will be true to indicate that there is no more
1228           // data available for this object.
1229 
1230           // If e.eof is not true, throw the exception as it
1231           // might have been caused by unrelated reasons.
1232           if (!e.eof) {
1233               throw (e);
1234           }
1235       }
1236 
1237       if (menuBar != null)
1238         menuBar.parent = this;
1239 
1240       // Ensure 1.1 serialized Frames can read & hook-up
1241       // owned windows properly
1242       //
1243       if (ownedWindows != null) {
1244           for (int i = 0; i < ownedWindows.size(); i++) {
1245               connectOwnedWindow((Window) ownedWindows.elementAt(i));
1246           }
1247           ownedWindows = null;
1248       }
1249     }
1250 
1251     /**
1252      * Initialize JNI field and method IDs
1253      */
1254     private static native void initIDs();
1255 
1256     /*
1257      * --- Accessibility Support ---
1258      *
1259      */
1260 
1261     /**
1262      * Gets the AccessibleContext associated with this Frame.
1263      * For frames, the AccessibleContext takes the form of an
1264      * AccessibleAWTFrame.
1265      * A new AccessibleAWTFrame instance is created if necessary.
1266      *
1267      * @return an AccessibleAWTFrame that serves as the
1268      *         AccessibleContext of this Frame
1269      * @since 1.3
1270      */
1271     public AccessibleContext getAccessibleContext() {
1272         if (accessibleContext == null) {
1273             accessibleContext = new AccessibleAWTFrame();
1274         }
1275         return accessibleContext;
1276     }
1277 
1278     /**
1279      * This class implements accessibility support for the
1280      * <code>Frame</code> class.  It provides an implementation of the
1281      * Java Accessibility API appropriate to frame user-interface elements.
1282      * @since 1.3
1283      */
1284     protected class AccessibleAWTFrame extends AccessibleAWTWindow
1285     {
1286         /*
1287          * JDK 1.3 serialVersionUID
1288          */
1289         private static final long serialVersionUID = -6172960752956030250L;
1290 
1291         /**
1292          * Get the role of this object.
1293          *
1294          * @return an instance of AccessibleRole describing the role of the
1295          * object
1296          * @see AccessibleRole
1297          */
1298         public AccessibleRole getAccessibleRole() {
1299             return AccessibleRole.FRAME;
1300         }
1301 
1302         /**
1303          * Get the state of this object.
1304          *
1305          * @return an instance of AccessibleStateSet containing the current
1306          * state set of the object
1307          * @see AccessibleState
1308          */
1309         public AccessibleStateSet getAccessibleStateSet() {
1310             AccessibleStateSet states = super.getAccessibleStateSet();
1311             if (getFocusOwner() != null) {
1312                 states.add(AccessibleState.ACTIVE);
1313             }
1314             if (isResizable()) {
1315                 states.add(AccessibleState.RESIZABLE);
1316             }
1317             return states;
1318         }
1319 
1320 
1321     } // inner class AccessibleAWTFrame
1322 
1323 }