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 | 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 /** 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