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