1 /*
2  * Copyright (c) 1995, 2020, 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 
26 package java.awt;
27 
28 import java.awt.event.KeyEvent;
29 import java.awt.event.WindowEvent;
30 import java.awt.peer.FramePeer;
31 import java.io.IOException;
32 import java.io.ObjectInputStream;
33 import java.io.ObjectOutputStream;
34 import java.io.Serializable;
35 import java.util.ArrayList;
36 import java.util.Vector;
37 
38 import javax.accessibility.AccessibleContext;
39 import javax.accessibility.AccessibleRole;
40 import javax.accessibility.AccessibleState;
41 import javax.accessibility.AccessibleStateSet;
42 
43 import sun.awt.AWTAccessor;
44 import 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" alt="Diagram of virtual device
87  * encompassing three physical screens and one primary physical screen. The
88  * primary physical screen shows (0,0) coords while a different physical screen
89  * shows (-80,-100) coords." style="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  */
138 public 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     /**
349      * The bitwise mask of frame state constants.
350      */
351     // XXX: uwe: abuse old field for now
352     // will need to take care of serialization
353     private int state = NORMAL;
354 
355     /**
356      * The Windows owned by the Frame.
357      * Note: in 1.2 this has been superseded by Window.ownedWindowList
358      *
359      * @serial
360      * @see java.awt.Window#ownedWindowList
361      */
362     Vector<Window> ownedWindows;
363 
364     private static final String base = "frame";
365     private static int nameCounter = 0;
366 
367     /*
368      * JDK 1.1 serialVersionUID
369      */
370      private static final long serialVersionUID = 2673458971256075116L;
371 
372     static {
373         /* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries()374         Toolkit.loadLibraries();
375         if (!GraphicsEnvironment.isHeadless()) {
initIDs()376             initIDs();
377         }
378     }
379 
380     /**
381      * Constructs a new instance of {@code Frame} that is
382      * initially invisible.  The title of the {@code Frame}
383      * is empty.
384      * @exception HeadlessException when
385      *     {@code GraphicsEnvironment.isHeadless()} returns {@code true}
386      * @see java.awt.GraphicsEnvironment#isHeadless()
387      * @see Component#setSize
388      * @see Component#setVisible(boolean)
389      */
Frame()390     public Frame() throws HeadlessException {
391         this("");
392     }
393 
394     /**
395      * Constructs a new, initially invisible {@code Frame} with the
396      * specified {@code GraphicsConfiguration}.
397      *
398      * @param gc the {@code GraphicsConfiguration}
399      * of the target screen device. If {@code gc}
400      * is {@code null}, the system default
401      * {@code GraphicsConfiguration} is assumed.
402      * @exception IllegalArgumentException if
403      * {@code gc} is not from a screen device.
404      * @exception HeadlessException when
405      *     {@code GraphicsEnvironment.isHeadless()} returns {@code true}
406      * @see java.awt.GraphicsEnvironment#isHeadless()
407      * @since     1.3
408      */
Frame(GraphicsConfiguration gc)409     public Frame(GraphicsConfiguration gc) {
410         this("", gc);
411     }
412 
413     /**
414      * Constructs a new, initially invisible {@code Frame} object
415      * with the specified title.
416      * @param title the title to be displayed in the frame's border.
417      *              A {@code null} value
418      *              is treated as an empty string, "".
419      * @exception HeadlessException when
420      *     {@code GraphicsEnvironment.isHeadless()} returns {@code true}
421      * @see java.awt.GraphicsEnvironment#isHeadless()
422      * @see java.awt.Component#setSize
423      * @see java.awt.Component#setVisible(boolean)
424      * @see java.awt.GraphicsConfiguration#getBounds
425      */
Frame(String title)426     public Frame(String title) throws HeadlessException {
427         init(title, null);
428     }
429 
430     /**
431      * Constructs a new, initially invisible {@code Frame} object
432      * with the specified title and a
433      * {@code GraphicsConfiguration}.
434      * @param title the title to be displayed in the frame's border.
435      *              A {@code null} value
436      *              is treated as an empty string, "".
437      * @param gc the {@code GraphicsConfiguration}
438      * of the target screen device.  If {@code gc} is
439      * {@code null}, the system default
440      * {@code GraphicsConfiguration} is assumed.
441      * @exception IllegalArgumentException if {@code gc}
442      * is not from a screen device.
443      * @exception HeadlessException when
444      *     {@code GraphicsEnvironment.isHeadless()} returns {@code true}
445      * @see java.awt.GraphicsEnvironment#isHeadless()
446      * @see java.awt.Component#setSize
447      * @see java.awt.Component#setVisible(boolean)
448      * @see java.awt.GraphicsConfiguration#getBounds
449      * @since 1.3
450      */
Frame(String title, GraphicsConfiguration gc)451     public Frame(String title, GraphicsConfiguration gc) {
452         super(gc);
453         init(title, gc);
454     }
455 
init(String title, GraphicsConfiguration gc)456     private void init(String title, GraphicsConfiguration gc) {
457         this.title = title;
458         SunToolkit.checkAndSetPolicy(this);
459     }
460 
461     /**
462      * Construct a name for this component.  Called by getName() when the
463      * name is null.
464      */
constructComponentName()465     String constructComponentName() {
466         synchronized (Frame.class) {
467             return base + nameCounter++;
468         }
469     }
470 
471     /**
472      * Makes this Frame displayable by connecting it to
473      * a native screen resource.  Making a frame displayable will
474      * cause any of its children to be made displayable.
475      * This method is called internally by the toolkit and should
476      * not be called directly by programs.
477      * @see Component#isDisplayable
478      * @see #removeNotify
479      */
addNotify()480     public void addNotify() {
481         synchronized (getTreeLock()) {
482             if (peer == null) {
483                 peer = getComponentFactory().createFrame(this);
484             }
485             FramePeer p = (FramePeer)peer;
486             MenuBar menuBar = this.menuBar;
487             if (menuBar != null) {
488                 mbManagement = true;
489                 menuBar.addNotify();
490                 p.setMenuBar(menuBar);
491             }
492             p.setMaximizedBounds(maximizedBounds);
493             super.addNotify();
494         }
495     }
496 
497     /**
498      * Gets the title of the frame.  The title is displayed in the
499      * frame's border.
500      * @return    the title of this frame, or an empty string ("")
501      *                if this frame doesn't have a title.
502      * @see       #setTitle(String)
503      */
getTitle()504     public String getTitle() {
505         return title;
506     }
507 
508     /**
509      * Sets the title for this frame to the specified string.
510      * @param title the title to be displayed in the frame's border.
511      *              A {@code null} value
512      *              is treated as an empty string, "".
513      * @see      #getTitle
514      */
setTitle(String title)515     public void setTitle(String title) {
516         String oldTitle = this.title;
517         if (title == null) {
518             title = "";
519         }
520 
521 
522         synchronized(this) {
523             this.title = title;
524             FramePeer peer = (FramePeer)this.peer;
525             if (peer != null) {
526                 peer.setTitle(title);
527             }
528         }
529         firePropertyChange("title", oldTitle, title);
530     }
531 
532     /**
533      * Returns the image to be displayed as the icon for this frame.
534      * <p>
535      * This method is obsolete and kept for backward compatibility
536      * only. Use {@link Window#getIconImages Window.getIconImages()} instead.
537      * <p>
538      * If a list of several images was specified as a Window's icon,
539      * this method will return the first item of the list.
540      *
541      * @return    the icon image for this frame, or {@code null}
542      *                    if this frame doesn't have an icon image.
543      * @see       #setIconImage(Image)
544      * @see       Window#getIconImages()
545      * @see       Window#setIconImages
546      */
getIconImage()547     public Image getIconImage() {
548         java.util.List<Image> icons = this.icons;
549         if (icons != null) {
550             if (icons.size() > 0) {
551                 return icons.get(0);
552             }
553         }
554         return null;
555     }
556 
557     /**
558      * {@inheritDoc}
559      */
setIconImage(Image image)560     public void setIconImage(Image image) {
561         super.setIconImage(image);
562     }
563 
564     /**
565      * Gets the menu bar for this frame.
566      * @return    the menu bar for this frame, or {@code null}
567      *                   if this frame doesn't have a menu bar.
568      * @see       #setMenuBar(MenuBar)
569      */
getMenuBar()570     public MenuBar getMenuBar() {
571         return menuBar;
572     }
573 
574     /**
575      * Sets the menu bar for this frame to the specified menu bar.
576      * @param     mb the menu bar being set.
577      *            If this parameter is {@code null} then any
578      *            existing menu bar on this frame is removed.
579      * @see       #getMenuBar
580      */
setMenuBar(MenuBar mb)581     public void setMenuBar(MenuBar mb) {
582         synchronized (getTreeLock()) {
583             if (menuBar == mb) {
584                 return;
585             }
586             if ((mb != null) && (mb.parent != null)) {
587                 mb.parent.remove(mb);
588             }
589             if (menuBar != null) {
590                 remove(menuBar);
591             }
592             menuBar = mb;
593             if (menuBar != null) {
594                 menuBar.parent = this;
595 
596                 FramePeer peer = (FramePeer)this.peer;
597                 if (peer != null) {
598                     mbManagement = true;
599                     menuBar.addNotify();
600                     invalidateIfValid();
601                     peer.setMenuBar(menuBar);
602                 }
603             }
604         }
605     }
606 
607     /**
608      * Indicates whether this frame is resizable by the user.
609      * By default, all frames are initially resizable.
610      * @return    {@code true} if the user can resize this frame;
611      *                        {@code false} otherwise.
612      * @see       java.awt.Frame#setResizable(boolean)
613      */
isResizable()614     public boolean isResizable() {
615         return resizable;
616     }
617 
618     /**
619      * Sets whether this frame is resizable by the user.
620      * @param    resizable   {@code true} if this frame is resizable;
621      *                       {@code false} otherwise.
622      * @see      java.awt.Frame#isResizable
623      */
setResizable(boolean resizable)624     public void setResizable(boolean resizable) {
625         boolean oldResizable = this.resizable;
626         boolean testvalid = false;
627 
628         synchronized (this) {
629             this.resizable = resizable;
630             FramePeer peer = (FramePeer)this.peer;
631             if (peer != null) {
632                 peer.setResizable(resizable);
633                 testvalid = true;
634             }
635         }
636 
637         // On some platforms, changing the resizable state affects
638         // the insets of the Frame. If we could, we'd call invalidate()
639         // from the peer, but we need to guarantee that we're not holding
640         // the Frame lock when we call invalidate().
641         if (testvalid) {
642             invalidateIfValid();
643         }
644         firePropertyChange("resizable", oldResizable, resizable);
645     }
646 
647 
648     /**
649      * Sets the state of this frame (obsolete).
650      * <p>
651      * In older versions of JDK a frame state could only be NORMAL or
652      * ICONIFIED.  Since JDK 1.4 set of supported frame states is
653      * expanded and frame state is represented as a bitwise mask.
654      * <p>
655      * For compatibility with applications developed
656      * earlier this method still accepts
657      * {@code Frame.NORMAL} and
658      * {@code Frame.ICONIFIED} only.  The iconic
659      * state of the frame is only changed, other aspects
660      * of frame state are not affected by this method. If
661      * the state passed to this method is neither {@code
662      * Frame.NORMAL} nor {@code Frame.ICONIFIED} the
663      * method performs no actions at all.
664      * <p>Note that if the state is not supported on a
665      * given platform, neither the state nor the return
666      * value of the {@link #getState} method will be
667      * changed. The application may determine whether a
668      * specific state is supported via the {@link
669      * java.awt.Toolkit#isFrameStateSupported} method.
670      * <p><b>If the frame is currently visible on the
671      * screen</b> (the {@link #isShowing} method returns
672      * {@code true}), the developer should examine the
673      * return value of the  {@link
674      * java.awt.event.WindowEvent#getNewState} method of
675      * the {@code WindowEvent} received through the
676      * {@link java.awt.event.WindowStateListener} to
677      * determine that the state has actually been
678      * changed.
679      * <p><b>If the frame is not visible on the
680      * screen</b>, the events may or may not be
681      * generated.  In this case the developer may assume
682      * that the state changes immediately after this
683      * method returns.  Later, when the {@code
684      * setVisible(true)} method is invoked, the frame
685      * will attempt to apply this state. Receiving any
686      * {@link
687      * java.awt.event.WindowEvent#WINDOW_STATE_CHANGED}
688      * events is not guaranteed in this case also.
689      *
690      * @param state either {@code Frame.NORMAL} or
691      *     {@code Frame.ICONIFIED}.
692      * @see #setExtendedState(int)
693      * @see java.awt.Window#addWindowStateListener
694      */
setState(int state)695     public synchronized void setState(int state) {
696         int current = getExtendedState();
697         if (state == ICONIFIED && (current & ICONIFIED) == 0) {
698             setExtendedState(current | ICONIFIED);
699         }
700         else if (state == NORMAL && (current & ICONIFIED) != 0) {
701             setExtendedState(current & ~ICONIFIED);
702         }
703     }
704 
705     /**
706      * Sets the state of this frame. The state is
707      * represented as a bitwise mask.
708      * <ul>
709      * <li>{@code NORMAL}
710      * <br>Indicates that no state bits are set.
711      * <li>{@code ICONIFIED}
712      * <li>{@code MAXIMIZED_HORIZ}
713      * <li>{@code MAXIMIZED_VERT}
714      * <li>{@code MAXIMIZED_BOTH}
715      * <br>Concatenates {@code MAXIMIZED_HORIZ}
716      * and {@code MAXIMIZED_VERT}.
717      * </ul>
718      * <p>Note that if the state is not supported on a
719      * given platform, neither the state nor the return
720      * value of the {@link #getExtendedState} method will
721      * be changed. The application may determine whether
722      * a specific state is supported via the {@link
723      * java.awt.Toolkit#isFrameStateSupported} method.
724      * <p><b>If the frame is currently visible on the
725      * screen</b> (the {@link #isShowing} method returns
726      * {@code true}), the developer should examine the
727      * return value of the {@link
728      * java.awt.event.WindowEvent#getNewState} method of
729      * the {@code WindowEvent} received through the
730      * {@link java.awt.event.WindowStateListener} to
731      * determine that the state has actually been
732      * changed.
733      * <p><b>If the frame is not visible on the
734      * screen</b>, the events may or may not be
735      * generated.  In this case the developer may assume
736      * that the state changes immediately after this
737      * method returns.  Later, when the {@code
738      * setVisible(true)} method is invoked, the frame
739      * will attempt to apply this state. Receiving any
740      * {@link
741      * java.awt.event.WindowEvent#WINDOW_STATE_CHANGED}
742      * events is not guaranteed in this case also.
743      *
744      * @param state a bitwise mask of frame state constants
745      * @since   1.4
746      * @see java.awt.Window#addWindowStateListener
747      */
setExtendedState(int state)748     public void setExtendedState(int state) {
749         if ( !isFrameStateSupported( state ) ) {
750             return;
751         }
752         synchronized (getObjectLock()) {
753             this.state = state;
754         }
755         // peer.setState must be called outside of object lock
756         // synchronization block to avoid possible deadlock
757         FramePeer peer = (FramePeer)this.peer;
758         if (peer != null) {
759             peer.setState(state);
760         }
761     }
isFrameStateSupported(int state)762     private boolean isFrameStateSupported(int state) {
763         if( !getToolkit().isFrameStateSupported( state ) ) {
764             // * Toolkit.isFrameStateSupported returns always false
765             // on compound state even if all parts are supported;
766             // * if part of state is not supported, state is not supported;
767             // * MAXIMIZED_BOTH is not a compound state.
768             if( ((state & ICONIFIED) != 0) &&
769                 !getToolkit().isFrameStateSupported( ICONIFIED )) {
770                 return false;
771             }else {
772                 state &= ~ICONIFIED;
773             }
774             return getToolkit().isFrameStateSupported( state );
775         }
776         return true;
777     }
778 
779     /**
780      * Gets the state of this frame (obsolete).
781      * <p>
782      * In older versions of JDK a frame state could only be NORMAL or
783      * ICONIFIED.  Since JDK 1.4 set of supported frame states is
784      * expanded and frame state is represented as a bitwise mask.
785      * <p>
786      * For compatibility with old programs this method still returns
787      * {@code Frame.NORMAL} and {@code Frame.ICONIFIED} but
788      * it only reports the iconic state of the frame, other aspects of
789      * frame state are not reported by this method.
790      *
791      * @return  {@code Frame.NORMAL} or {@code Frame.ICONIFIED}.
792      * @see     #setState(int)
793      * @see     #getExtendedState
794      */
getState()795     public synchronized int getState() {
796         return (getExtendedState() & ICONIFIED) != 0 ? ICONIFIED : NORMAL;
797     }
798 
799 
800     /**
801      * Gets the state of this frame. The state is
802      * represented as a bitwise mask.
803      * <ul>
804      * <li>{@code NORMAL}
805      * <br>Indicates that no state bits are set.
806      * <li>{@code ICONIFIED}
807      * <li>{@code MAXIMIZED_HORIZ}
808      * <li>{@code MAXIMIZED_VERT}
809      * <li>{@code MAXIMIZED_BOTH}
810      * <br>Concatenates {@code MAXIMIZED_HORIZ}
811      * and {@code MAXIMIZED_VERT}.
812      * </ul>
813      *
814      * @return  a bitwise mask of frame state constants
815      * @see     #setExtendedState(int)
816      * @since 1.4
817      */
getExtendedState()818     public int getExtendedState() {
819         synchronized (getObjectLock()) {
820             return state;
821         }
822     }
823 
824     static {
AWTAccessor.setFrameAccessor( new AWTAccessor.FrameAccessor() { public void setExtendedState(Frame frame, int state) { synchronized(frame.getObjectLock()) { frame.state = state; } } public int getExtendedState(Frame frame) { synchronized(frame.getObjectLock()) { return frame.state; } } public Rectangle getMaximizedBounds(Frame frame) { synchronized(frame.getObjectLock()) { return frame.maximizedBounds; } } } )825         AWTAccessor.setFrameAccessor(
826             new AWTAccessor.FrameAccessor() {
827                 public void setExtendedState(Frame frame, int state) {
828                     synchronized(frame.getObjectLock()) {
829                         frame.state = state;
830                     }
831                 }
832                 public int getExtendedState(Frame frame) {
833                     synchronized(frame.getObjectLock()) {
834                         return frame.state;
835                     }
836                 }
837                 public Rectangle getMaximizedBounds(Frame frame) {
838                     synchronized(frame.getObjectLock()) {
839                         return frame.maximizedBounds;
840                     }
841                 }
842             }
843         );
844     }
845 
846     /**
847      * Sets the maximized bounds for this frame.
848      * <p>
849      * When a frame is in maximized state the system supplies some
850      * defaults bounds.  This method allows some or all of those
851      * system supplied values to be overridden.
852      * <p>
853      * If {@code bounds} is {@code null}, accept bounds
854      * supplied by the system.  If non-{@code null} you can
855      * override some of the system supplied values while accepting
856      * others by setting those fields you want to accept from system
857      * to {@code Integer.MAX_VALUE}.
858      * <p>
859      * Note, the given maximized bounds are used as a hint for the native
860      * system, because the underlying platform may not support setting the
861      * location and/or size of the maximized windows.  If that is the case, the
862      * provided values do not affect the appearance of the frame in the
863      * maximized state.
864      *
865      * @param bounds  bounds for the maximized state
866      * @see #getMaximizedBounds()
867      * @since 1.4
868      */
setMaximizedBounds(Rectangle bounds)869     public void setMaximizedBounds(Rectangle bounds) {
870         synchronized(getObjectLock()) {
871             this.maximizedBounds = bounds;
872         }
873         FramePeer peer = (FramePeer)this.peer;
874         if (peer != null) {
875             peer.setMaximizedBounds(bounds);
876         }
877     }
878 
879     /**
880      * Gets maximized bounds for this frame.
881      * Some fields may contain {@code Integer.MAX_VALUE} to indicate
882      * that system supplied values for this field must be used.
883      *
884      * @return  maximized bounds for this frame;  may be {@code null}
885      * @see     #setMaximizedBounds(Rectangle)
886      * @since   1.4
887      */
getMaximizedBounds()888     public Rectangle getMaximizedBounds() {
889         synchronized(getObjectLock()) {
890             return maximizedBounds;
891         }
892     }
893 
894 
895     /**
896      * Disables or enables decorations for this frame.
897      * <p>
898      * This method can only be called while the frame is not displayable. To
899      * make this frame decorated, it must be opaque and have the default shape,
900      * otherwise the {@code IllegalComponentStateException} will be thrown.
901      * Refer to {@link Window#setShape}, {@link Window#setOpacity} and {@link
902      * Window#setBackground} for details
903      *
904      * @param  undecorated {@code true} if no frame decorations are to be
905      *         enabled; {@code false} if frame decorations are to be enabled
906      *
907      * @throws IllegalComponentStateException if the frame is displayable
908      * @throws IllegalComponentStateException if {@code undecorated} is
909      *      {@code false}, and this frame does not have the default shape
910      * @throws IllegalComponentStateException if {@code undecorated} is
911      *      {@code false}, and this frame opacity is less than {@code 1.0f}
912      * @throws IllegalComponentStateException if {@code undecorated} is
913      *      {@code false}, and the alpha value of this frame background
914      *      color is less than {@code 1.0f}
915      *
916      * @see    #isUndecorated
917      * @see    Component#isDisplayable
918      * @see    Window#getShape
919      * @see    Window#getOpacity
920      * @see    Window#getBackground
921      * @see    javax.swing.JFrame#setDefaultLookAndFeelDecorated(boolean)
922      *
923      * @since 1.4
924      */
setUndecorated(boolean undecorated)925     public void setUndecorated(boolean undecorated) {
926         /* Make sure we don't run in the middle of peer creation.*/
927         synchronized (getTreeLock()) {
928             if (isDisplayable()) {
929                 throw new IllegalComponentStateException("The frame is displayable.");
930             }
931             if (!undecorated) {
932                 if (getOpacity() < 1.0f) {
933                     throw new IllegalComponentStateException("The frame is not opaque");
934                 }
935                 if (getShape() != null) {
936                     throw new IllegalComponentStateException("The frame does not have a default shape");
937                 }
938                 Color bg = getBackground();
939                 if ((bg != null) && (bg.getAlpha() < 255)) {
940                     throw new IllegalComponentStateException("The frame background color is not opaque");
941                 }
942             }
943             this.undecorated = undecorated;
944         }
945     }
946 
947     /**
948      * Indicates whether this frame is undecorated.
949      * By default, all frames are initially decorated.
950      * @return    {@code true} if frame is undecorated;
951      *                        {@code false} otherwise.
952      * @see       java.awt.Frame#setUndecorated(boolean)
953      * @since 1.4
954      */
isUndecorated()955     public boolean isUndecorated() {
956         return undecorated;
957     }
958 
959     /**
960      * {@inheritDoc}
961      */
962     @Override
setOpacity(float opacity)963     public void setOpacity(float opacity) {
964         synchronized (getTreeLock()) {
965             if ((opacity < 1.0f) && !isUndecorated()) {
966                 throw new IllegalComponentStateException("The frame is decorated");
967             }
968             super.setOpacity(opacity);
969         }
970     }
971 
972     /**
973      * {@inheritDoc}
974      */
975     @Override
setShape(Shape shape)976     public void setShape(Shape shape) {
977         synchronized (getTreeLock()) {
978             if ((shape != null) && !isUndecorated()) {
979                 throw new IllegalComponentStateException("The frame is decorated");
980             }
981             super.setShape(shape);
982         }
983     }
984 
985     /**
986      * {@inheritDoc}
987      */
988     @Override
setBackground(Color bgColor)989     public void setBackground(Color bgColor) {
990         synchronized (getTreeLock()) {
991             if ((bgColor != null) && (bgColor.getAlpha() < 255) && !isUndecorated()) {
992                 throw new IllegalComponentStateException("The frame is decorated");
993             }
994             super.setBackground(bgColor);
995         }
996     }
997 
998     /**
999      * Removes the specified menu bar from this frame.
1000      * @param    m   the menu component to remove.
1001      *           If {@code m} is {@code null}, then
1002      *           no action is taken
1003      */
remove(MenuComponent m)1004     public void remove(MenuComponent m) {
1005         if (m == null) {
1006             return;
1007         }
1008         synchronized (getTreeLock()) {
1009             if (m == menuBar) {
1010                 menuBar = null;
1011                 FramePeer peer = (FramePeer)this.peer;
1012                 if (peer != null) {
1013                     mbManagement = true;
1014                     invalidateIfValid();
1015                     peer.setMenuBar(null);
1016                     m.removeNotify();
1017                 }
1018                 m.parent = null;
1019             } else {
1020                 super.remove(m);
1021             }
1022         }
1023     }
1024 
1025     /**
1026      * Makes this Frame undisplayable by removing its connection
1027      * to its native screen resource. Making a Frame undisplayable
1028      * will cause any of its children to be made undisplayable.
1029      * This method is called by the toolkit internally and should
1030      * not be called directly by programs.
1031      * @see Component#isDisplayable
1032      * @see #addNotify
1033      */
removeNotify()1034     public void removeNotify() {
1035         synchronized (getTreeLock()) {
1036             FramePeer peer = (FramePeer)this.peer;
1037             if (peer != null) {
1038                 // get the latest Frame state before disposing
1039                 getState();
1040 
1041                 if (menuBar != null) {
1042                     mbManagement = true;
1043                     peer.setMenuBar(null);
1044                     menuBar.removeNotify();
1045                 }
1046             }
1047             super.removeNotify();
1048         }
1049     }
1050 
postProcessKeyEvent(KeyEvent e)1051     void postProcessKeyEvent(KeyEvent e) {
1052         if (menuBar != null && menuBar.handleShortcut(e)) {
1053             e.consume();
1054             return;
1055         }
1056         super.postProcessKeyEvent(e);
1057     }
1058 
1059     /**
1060      * Returns a string representing the state of this {@code Frame}.
1061      * This method is intended to be used only for debugging purposes, and the
1062      * content and format of the returned string may vary between
1063      * implementations. The returned string may be empty but may not be
1064      * {@code null}.
1065      *
1066      * @return the parameter string of this frame
1067      */
paramString()1068     protected String paramString() {
1069         String str = super.paramString();
1070         if (title != null) {
1071             str += ",title=" + title;
1072         }
1073         if (resizable) {
1074             str += ",resizable";
1075         }
1076         int state = getExtendedState();
1077         if (state == NORMAL) {
1078             str += ",normal";
1079         }
1080         else {
1081             if ((state & ICONIFIED) != 0) {
1082                 str += ",iconified";
1083             }
1084             if ((state & MAXIMIZED_BOTH) == MAXIMIZED_BOTH) {
1085                 str += ",maximized";
1086             }
1087             else if ((state & MAXIMIZED_HORIZ) != 0) {
1088                 str += ",maximized_horiz";
1089             }
1090             else if ((state & MAXIMIZED_VERT) != 0) {
1091                 str += ",maximized_vert";
1092             }
1093         }
1094         return str;
1095     }
1096 
1097     /**
1098      * Sets the cursor for this frame to the specified type.
1099      *
1100      * @param  cursorType the cursor type
1101      * @deprecated As of JDK version 1.1,
1102      * replaced by {@code Component.setCursor(Cursor)}.
1103      */
1104     @Deprecated
setCursor(int cursorType)1105     public void setCursor(int cursorType) {
1106         if (cursorType < DEFAULT_CURSOR || cursorType > MOVE_CURSOR) {
1107             throw new IllegalArgumentException("illegal cursor type");
1108         }
1109         setCursor(Cursor.getPredefinedCursor(cursorType));
1110     }
1111 
1112     /**
1113      * @deprecated As of JDK version 1.1,
1114      * replaced by {@code Component.getCursor()}.
1115      * @return the cursor type for this frame
1116      */
1117     @Deprecated
getCursorType()1118     public int getCursorType() {
1119         return (getCursor().getType());
1120     }
1121 
1122     /**
1123      * Returns an array of all {@code Frame}s created by this application.
1124      * If called from an applet, the array includes only the {@code Frame}s
1125      * accessible by that applet.
1126      * <p>
1127      * <b>Warning:</b> this method may return system created frames, such
1128      * as a shared, hidden frame which is used by Swing. Applications
1129      * should not assume the existence of these frames, nor should an
1130      * application assume anything about these frames such as component
1131      * positions, {@code LayoutManager}s or serialization.
1132      * <p>
1133      * <b>Note</b>: To obtain a list of all ownerless windows, including
1134      * ownerless {@code Dialog}s (introduced in release 1.6), use {@link
1135      * Window#getOwnerlessWindows Window.getOwnerlessWindows}.
1136      *
1137      * @return the array of all {@code Frame}s created by this application
1138      *
1139      * @see Window#getWindows()
1140      * @see Window#getOwnerlessWindows
1141      *
1142      * @since 1.2
1143      */
getFrames()1144     public static Frame[] getFrames() {
1145         Window[] allWindows = Window.getWindows();
1146 
1147         int frameCount = 0;
1148         for (Window w : allWindows) {
1149             if (w instanceof Frame) {
1150                 frameCount++;
1151             }
1152         }
1153 
1154         Frame[] frames = new Frame[frameCount];
1155         int c = 0;
1156         for (Window w : allWindows) {
1157             if (w instanceof Frame) {
1158                 frames[c++] = (Frame)w;
1159             }
1160         }
1161 
1162         return frames;
1163     }
1164 
1165     /* Serialization support.  If there's a MenuBar we restore
1166      * its (transient) parent field here.  Likewise for top level
1167      * windows that are "owned" by this frame.
1168      */
1169 
1170     /**
1171      * {@code Frame}'s Serialized Data Version.
1172      *
1173      * @serial
1174      */
1175     private int frameSerializedDataVersion = 1;
1176 
1177     /**
1178      * Writes default serializable fields to stream.  Writes
1179      * an optional serializable icon {@code Image}, which is
1180      * available as of 1.4.
1181      *
1182      * @param  s the {@code ObjectOutputStream} to write
1183      * @throws IOException if an I/O error occurs
1184      * @serialData an optional icon {@code Image}
1185      * @see java.awt.Image
1186      * @see #getIconImage
1187      * @see #setIconImage(Image)
1188      * @see #readObject(ObjectInputStream)
1189      */
writeObject(ObjectOutputStream s)1190     private void writeObject(ObjectOutputStream s)
1191       throws IOException
1192     {
1193         s.defaultWriteObject();
1194         if (icons != null && icons.size() > 0) {
1195             Image icon1 = icons.get(0);
1196             if (icon1 instanceof Serializable) {
1197                 s.writeObject(icon1);
1198                 return;
1199             }
1200         }
1201         s.writeObject(null);
1202     }
1203 
1204     /**
1205      * Reads the {@code ObjectInputStream}.  Tries
1206      * to read an icon {@code Image}, which is optional
1207      * data available as of 1.4.  If an icon {@code Image}
1208      * is not available, but anything other than an EOF
1209      * is detected, an {@code OptionalDataException}
1210      * will be thrown.
1211      * Unrecognized keys or values will be ignored.
1212      *
1213      * @param  s the {@code ObjectInputStream} to read
1214      * @throws ClassNotFoundException if the class of a serialized object could
1215      *         not be found
1216      * @throws java.io.OptionalDataException if an icon {@code Image} is not
1217      *         available, but anything other than an EOF is detected
1218      * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()}
1219      *         returns {@code true}
1220      * @see java.awt.GraphicsEnvironment#isHeadless()
1221      * @see java.awt.Image
1222      * @see #getIconImage
1223      * @see #setIconImage(Image)
1224      * @see #writeObject(ObjectOutputStream)
1225      */
readObject(ObjectInputStream s)1226     private void readObject(ObjectInputStream s)
1227       throws ClassNotFoundException, IOException, HeadlessException
1228     {
1229       // HeadlessException is thrown by Window's readObject
1230       s.defaultReadObject();
1231       try {
1232           Image icon = (Image) s.readObject();
1233           if (icons == null) {
1234               icons = new ArrayList<Image>();
1235               icons.add(icon);
1236           }
1237       } catch (java.io.OptionalDataException e) {
1238           // pre-1.4 instances will not have this optional data.
1239           // 1.6 and later instances serialize icons in the Window class
1240           // e.eof will be true to indicate that there is no more
1241           // data available for this object.
1242 
1243           // If e.eof is not true, throw the exception as it
1244           // might have been caused by unrelated reasons.
1245           if (!e.eof) {
1246               throw (e);
1247           }
1248       }
1249 
1250       if (menuBar != null)
1251         menuBar.parent = this;
1252 
1253       // Ensure 1.1 serialized Frames can read & hook-up
1254       // owned windows properly
1255       //
1256       if (ownedWindows != null) {
1257           for (int i = 0; i < ownedWindows.size(); i++) {
1258               connectOwnedWindow(ownedWindows.elementAt(i));
1259           }
1260           ownedWindows = null;
1261       }
1262     }
1263 
1264     /**
1265      * Initialize JNI field and method IDs
1266      */
initIDs()1267     private static native void initIDs();
1268 
1269     /*
1270      * --- Accessibility Support ---
1271      *
1272      */
1273 
1274     /**
1275      * Gets the AccessibleContext associated with this Frame.
1276      * For frames, the AccessibleContext takes the form of an
1277      * AccessibleAWTFrame.
1278      * A new AccessibleAWTFrame instance is created if necessary.
1279      *
1280      * @return an AccessibleAWTFrame that serves as the
1281      *         AccessibleContext of this Frame
1282      * @since 1.3
1283      */
getAccessibleContext()1284     public AccessibleContext getAccessibleContext() {
1285         if (accessibleContext == null) {
1286             accessibleContext = new AccessibleAWTFrame();
1287         }
1288         return accessibleContext;
1289     }
1290 
1291     /**
1292      * This class implements accessibility support for the
1293      * {@code Frame} class.  It provides an implementation of the
1294      * Java Accessibility API appropriate to frame user-interface elements.
1295      * @since 1.3
1296      */
1297     protected class AccessibleAWTFrame extends AccessibleAWTWindow
1298     {
1299         /*
1300          * JDK 1.3 serialVersionUID
1301          */
1302         private static final long serialVersionUID = -6172960752956030250L;
1303 
1304         /**
1305          * Constructs an {@code AccessibleAWTFrame}.
1306          */
AccessibleAWTFrame()1307         protected AccessibleAWTFrame() {}
1308 
1309         /**
1310          * Get the role of this object.
1311          *
1312          * @return an instance of AccessibleRole describing the role of the
1313          * object
1314          * @see AccessibleRole
1315          */
getAccessibleRole()1316         public AccessibleRole getAccessibleRole() {
1317             return AccessibleRole.FRAME;
1318         }
1319 
1320         /**
1321          * Get the state of this object.
1322          *
1323          * @return an instance of AccessibleStateSet containing the current
1324          * state set of the object
1325          * @see AccessibleState
1326          */
getAccessibleStateSet()1327         public AccessibleStateSet getAccessibleStateSet() {
1328             AccessibleStateSet states = super.getAccessibleStateSet();
1329             if (getFocusOwner() != null) {
1330                 states.add(AccessibleState.ACTIVE);
1331             }
1332             if (isResizable()) {
1333                 states.add(AccessibleState.RESIZABLE);
1334             }
1335             return states;
1336         }
1337 
1338 
1339     } // inner class AccessibleAWTFrame
1340 
1341 }
1342