1 /* 2 * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.awt; 26 27 import java.awt.event.KeyEvent; 28 import java.awt.event.WindowEvent; 29 import java.awt.peer.FramePeer; 30 import java.io.IOException; 31 import java.io.ObjectInputStream; 32 import java.io.ObjectOutputStream; 33 import java.io.Serializable; 34 import java.util.ArrayList; 35 import java.util.Vector; 36 37 import javax.accessibility.AccessibleContext; 38 import javax.accessibility.AccessibleRole; 39 import javax.accessibility.AccessibleState; 40 import javax.accessibility.AccessibleStateSet; 41 import javax.swing.WindowConstants; 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 | MAXIMIZED_HORIZ</code>. 268 * 269 * <p>Note that the correct test for frame being fully maximized is 270 * <pre> 271 * (state & 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 & 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 }