1 /* 2 * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.awt; 26 27 import java.awt.peer.DialogPeer; 28 import java.awt.event.*; 29 import java.io.ObjectInputStream; 30 import java.io.IOException; 31 import java.util.Iterator; 32 import java.util.concurrent.atomic.AtomicLong; 33 import java.security.AccessController; 34 import java.security.PrivilegedAction; 35 import javax.accessibility.*; 36 import sun.awt.AppContext; 37 import sun.awt.AWTPermissions; 38 import sun.awt.SunToolkit; 39 import sun.awt.util.IdentityArrayList; 40 import sun.awt.util.IdentityLinkedList; 41 import java.security.AccessControlException; 42 43 /** 44 * A Dialog is a top-level window with a title and a border 45 * that is typically used to take some form of input from the user. 46 * 47 * The size of the dialog includes any area designated for the 48 * border. The dimensions of the border area can be obtained 49 * using the {@code getInsets} method, however, since 50 * these dimensions are platform-dependent, a valid insets 51 * value cannot be obtained until the dialog is made displayable 52 * by either calling {@code pack} or {@code show}. 53 * Since the border area is included in the overall size of the 54 * dialog, the border effectively obscures a portion of the dialog, 55 * constraining the area available for rendering and/or displaying 56 * subcomponents to the rectangle which has an upper-left corner 57 * location of {@code (insets.left, insets.top)}, and has a size of 58 * {@code width - (insets.left + insets.right)} by 59 * {@code height - (insets.top + insets.bottom)}. 60 * <p> 61 * The default layout for a dialog is {@code BorderLayout}. 62 * <p> 63 * A dialog may have its native decorations (i.e. Frame & Titlebar) turned off 64 * with {@code setUndecorated}. This can only be done while the dialog 65 * is not {@link Component#isDisplayable() displayable}. 66 * <p> 67 * A dialog may have another window as its owner when it's constructed. When 68 * the owner window of a visible dialog is minimized, the dialog will 69 * automatically be hidden from the user. When the owner window is subsequently 70 * restored, the dialog is made visible to the user again. 71 * <p> 72 * In a multi-screen environment, you can create a {@code Dialog} 73 * on a different screen device than its owner. See {@link java.awt.Frame} for 74 * more information. 75 * <p> 76 * A dialog can be either modeless (the default) or modal. A modal 77 * dialog is one which blocks input to some other top-level windows 78 * in the application, except for any windows created with the dialog 79 * as their owner. See <a href="doc-files/Modality.html">AWT Modality</a> 80 * specification for details. 81 * <p> 82 * Dialogs are capable of generating the following 83 * {@code WindowEvents}: 84 * {@code WindowOpened}, {@code WindowClosing}, 85 * {@code WindowClosed}, {@code WindowActivated}, 86 * {@code WindowDeactivated}, {@code WindowGainedFocus}, 87 * {@code WindowLostFocus}. 88 * 89 * @see WindowEvent 90 * @see Window#addWindowListener 91 * 92 * @author Sami Shaio 93 * @author Arthur van Hoff 94 * @since 1.0 95 */ 96 public class Dialog extends Window { 97 98 static { 99 /* ensure that the necessary native libraries are loaded */ Toolkit.loadLibraries()100 Toolkit.loadLibraries(); 101 if (!GraphicsEnvironment.isHeadless()) { initIDs()102 initIDs(); 103 } 104 } 105 106 /** 107 * A dialog's resizable property. Will be true 108 * if the Dialog is to be resizable, otherwise 109 * it will be false. 110 * 111 * @serial 112 * @see #setResizable(boolean) 113 */ 114 boolean resizable = true; 115 116 117 /** 118 * This field indicates whether the dialog is undecorated. 119 * This property can only be changed while the dialog is not displayable. 120 * {@code undecorated} will be true if the dialog is 121 * undecorated, otherwise it will be false. 122 * 123 * @serial 124 * @see #setUndecorated(boolean) 125 * @see #isUndecorated() 126 * @see Component#isDisplayable() 127 * @since 1.4 128 */ 129 boolean undecorated = false; 130 131 private transient boolean initialized = false; 132 133 /** 134 * Modal dialogs block all input to some top-level windows. 135 * Whether a particular window is blocked depends on dialog's type 136 * of modality; this is called the "scope of blocking". The 137 * {@code ModalityType} enum specifies modal types and their 138 * associated scopes. 139 * 140 * @see Dialog#getModalityType 141 * @see Dialog#setModalityType 142 * @see Toolkit#isModalityTypeSupported 143 * 144 * @since 1.6 145 */ 146 public static enum ModalityType { 147 /** 148 * {@code MODELESS} dialog doesn't block any top-level windows. 149 */ 150 MODELESS, 151 /** 152 * A {@code DOCUMENT_MODAL} dialog blocks input to all top-level windows 153 * from the same document except those from its own child hierarchy. 154 * A document is a top-level window without an owner. It may contain child 155 * windows that, together with the top-level window are treated as a single 156 * solid document. Since every top-level window must belong to some 157 * document, its root can be found as the top-nearest window without an owner. 158 */ 159 DOCUMENT_MODAL, 160 /** 161 * An {@code APPLICATION_MODAL} dialog blocks all top-level windows 162 * from the same Java application except those from its own child hierarchy. 163 * If there are several applets launched in a browser, they can be 164 * treated either as separate applications or a single one. This behavior 165 * is implementation-dependent. 166 */ 167 APPLICATION_MODAL, 168 /** 169 * A {@code TOOLKIT_MODAL} dialog blocks all top-level windows run 170 * from the same toolkit except those from its own child hierarchy. If there 171 * are several applets launched in a browser, all of them run with the same 172 * toolkit; thus, a toolkit-modal dialog displayed by an applet may affect 173 * other applets and all windows of the browser instance which embeds the 174 * Java runtime environment for this toolkit. 175 * Special {@code AWTPermission} "toolkitModality" must be granted to use 176 * toolkit-modal dialogs. If a {@code TOOLKIT_MODAL} dialog is being created 177 * and this permission is not granted, a {@code SecurityException} will be 178 * thrown, and no dialog will be created. If a modality type is being changed 179 * to {@code TOOLKIT_MODAL} and this permission is not granted, a 180 * {@code SecurityException} will be thrown, and the modality type will 181 * be left unchanged. 182 */ 183 TOOLKIT_MODAL 184 }; 185 186 /** 187 * Default modality type for modal dialogs. The default modality type is 188 * {@code APPLICATION_MODAL}. Calling the oldstyle {@code setModal(true)} 189 * is equal to {@code setModalityType(DEFAULT_MODALITY_TYPE)}. 190 * 191 * @see java.awt.Dialog.ModalityType 192 * @see java.awt.Dialog#setModal 193 * 194 * @since 1.6 195 */ 196 public static final ModalityType DEFAULT_MODALITY_TYPE = ModalityType.APPLICATION_MODAL; 197 198 /** 199 * True if this dialog is modal, false is the dialog is modeless. 200 * A modal dialog blocks user input to some application top-level 201 * windows. This field is kept only for backwards compatibility. Use the 202 * {@link Dialog.ModalityType ModalityType} enum instead. 203 * 204 * @serial 205 * 206 * @see #isModal 207 * @see #setModal 208 * @see #getModalityType 209 * @see #setModalityType 210 * @see ModalityType 211 * @see ModalityType#MODELESS 212 * @see #DEFAULT_MODALITY_TYPE 213 */ 214 boolean modal; 215 216 /** 217 * Modality type of this dialog. If the dialog's modality type is not 218 * {@link Dialog.ModalityType#MODELESS ModalityType.MODELESS}, it blocks all 219 * user input to some application top-level windows. 220 * 221 * @serial 222 * 223 * @see ModalityType 224 * @see #getModalityType 225 * @see #setModalityType 226 * 227 * @since 1.6 228 */ 229 ModalityType modalityType; 230 231 /** 232 * Any top-level window can be marked not to be blocked by modal 233 * dialogs. This is called "modal exclusion". This enum specifies 234 * the possible modal exclusion types. 235 * 236 * @see Window#getModalExclusionType 237 * @see Window#setModalExclusionType 238 * @see Toolkit#isModalExclusionTypeSupported 239 * 240 * @since 1.6 241 */ 242 public static enum ModalExclusionType { 243 /** 244 * No modal exclusion. 245 */ 246 NO_EXCLUDE, 247 /** 248 * {@code APPLICATION_EXCLUDE} indicates that a top-level window 249 * won't be blocked by any application-modal dialogs. Also, it isn't 250 * blocked by document-modal dialogs from outside of its child hierarchy. 251 */ 252 APPLICATION_EXCLUDE, 253 /** 254 * {@code TOOLKIT_EXCLUDE} indicates that a top-level window 255 * won't be blocked by application-modal or toolkit-modal dialogs. Also, 256 * it isn't blocked by document-modal dialogs from outside of its 257 * child hierarchy. 258 * The "toolkitModality" {@code AWTPermission} must be granted 259 * for this exclusion. If an exclusion property is being changed to 260 * {@code TOOLKIT_EXCLUDE} and this permission is not granted, a 261 * {@code SecurityException} will be thrown, and the exclusion 262 * property will be left unchanged. 263 */ 264 TOOLKIT_EXCLUDE 265 }; 266 267 /* operations with this list should be synchronized on tree lock*/ 268 static transient IdentityArrayList<Dialog> modalDialogs = new IdentityArrayList<Dialog>(); 269 270 transient IdentityArrayList<Window> blockedWindows = new IdentityArrayList<Window>(); 271 272 /** 273 * Specifies the title of the Dialog. 274 * This field can be null. 275 * 276 * @serial 277 * @see #getTitle() 278 * @see #setTitle(String) 279 */ 280 String title; 281 282 private transient ModalEventFilter modalFilter; 283 private transient volatile SecondaryLoop secondaryLoop; 284 285 /* 286 * Indicates that this dialog is being hidden. This flag is set to true at 287 * the beginning of hide() and to false at the end of hide(). 288 * 289 * @see #hide() 290 * @see #hideAndDisposePreHandler() 291 * @see #hideAndDisposeHandler() 292 * @see #shouldBlock() 293 */ 294 transient volatile boolean isInHide = false; 295 296 /* 297 * Indicates that this dialog is being disposed. This flag is set to true at 298 * the beginning of doDispose() and to false at the end of doDispose(). 299 * 300 * @see #hide() 301 * @see #hideAndDisposePreHandler() 302 * @see #hideAndDisposeHandler() 303 * @see #doDispose() 304 */ 305 transient volatile boolean isInDispose = false; 306 307 private static final String base = "dialog"; 308 private static int nameCounter = 0; 309 310 /* 311 * JDK 1.1 serialVersionUID 312 */ 313 private static final long serialVersionUID = 5920926903803293709L; 314 315 /** 316 * Constructs an initially invisible, modeless {@code Dialog} with 317 * the specified owner {@code Frame} and an empty title. 318 * 319 * @param owner the owner of the dialog or {@code null} if 320 * this dialog has no owner 321 * @exception java.lang.IllegalArgumentException if the {@code owner}'s 322 * {@code GraphicsConfiguration} is not from a screen device 323 * @exception HeadlessException when 324 * {@code GraphicsEnvironment.isHeadless()} returns {@code true} 325 * 326 * @see java.awt.GraphicsEnvironment#isHeadless 327 * @see Component#setSize 328 * @see Component#setVisible 329 */ Dialog(Frame owner)330 public Dialog(Frame owner) { 331 this(owner, "", false); 332 } 333 334 /** 335 * Constructs an initially invisible {@code Dialog} with the specified 336 * owner {@code Frame} and modality and an empty title. 337 * 338 * @param owner the owner of the dialog or {@code null} if 339 * this dialog has no owner 340 * @param modal specifies whether dialog blocks user input to other top-level 341 * windows when shown. If {@code false}, the dialog is {@code MODELESS}; 342 * if {@code true}, the modality type property is set to 343 * {@code DEFAULT_MODALITY_TYPE} 344 * @exception java.lang.IllegalArgumentException if the {@code owner}'s 345 * {@code GraphicsConfiguration} is not from a screen device 346 * @exception HeadlessException when 347 * {@code GraphicsEnvironment.isHeadless()} returns {@code true} 348 * 349 * @see java.awt.Dialog.ModalityType 350 * @see java.awt.Dialog.ModalityType#MODELESS 351 * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE 352 * @see java.awt.Dialog#setModal 353 * @see java.awt.Dialog#setModalityType 354 * @see java.awt.GraphicsEnvironment#isHeadless 355 */ Dialog(Frame owner, boolean modal)356 public Dialog(Frame owner, boolean modal) { 357 this(owner, "", modal); 358 } 359 360 /** 361 * Constructs an initially invisible, modeless {@code Dialog} with 362 * the specified owner {@code Frame} and title. 363 * 364 * @param owner the owner of the dialog or {@code null} if 365 * this dialog has no owner 366 * @param title the title of the dialog or {@code null} if this dialog 367 * has no title 368 * @exception IllegalArgumentException if the {@code owner}'s 369 * {@code GraphicsConfiguration} is not from a screen device 370 * @exception HeadlessException when 371 * {@code GraphicsEnvironment.isHeadless()} returns {@code true} 372 * 373 * @see java.awt.GraphicsEnvironment#isHeadless 374 * @see Component#setSize 375 * @see Component#setVisible 376 */ Dialog(Frame owner, String title)377 public Dialog(Frame owner, String title) { 378 this(owner, title, false); 379 } 380 381 /** 382 * Constructs an initially invisible {@code Dialog} with the 383 * specified owner {@code Frame}, title and modality. 384 * 385 * @param owner the owner of the dialog or {@code null} if 386 * this dialog has no owner 387 * @param title the title of the dialog or {@code null} if this dialog 388 * has no title 389 * @param modal specifies whether dialog blocks user input to other top-level 390 * windows when shown. If {@code false}, the dialog is {@code MODELESS}; 391 * if {@code true}, the modality type property is set to 392 * {@code DEFAULT_MODALITY_TYPE} 393 * @exception java.lang.IllegalArgumentException if the {@code owner}'s 394 * {@code GraphicsConfiguration} is not from a screen device 395 * @exception HeadlessException when 396 * {@code GraphicsEnvironment.isHeadless()} returns {@code true} 397 * 398 * @see java.awt.Dialog.ModalityType 399 * @see java.awt.Dialog.ModalityType#MODELESS 400 * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE 401 * @see java.awt.Dialog#setModal 402 * @see java.awt.Dialog#setModalityType 403 * @see java.awt.GraphicsEnvironment#isHeadless 404 * @see Component#setSize 405 * @see Component#setVisible 406 */ Dialog(Frame owner, String title, boolean modal)407 public Dialog(Frame owner, String title, boolean modal) { 408 this(owner, title, modal ? DEFAULT_MODALITY_TYPE : ModalityType.MODELESS); 409 } 410 411 /** 412 * Constructs an initially invisible {@code Dialog} with the specified owner 413 * {@code Frame}, title, modality, and {@code GraphicsConfiguration}. 414 * @param owner the owner of the dialog or {@code null} if this dialog 415 * has no owner 416 * @param title the title of the dialog or {@code null} if this dialog 417 * has no title 418 * @param modal specifies whether dialog blocks user input to other top-level 419 * windows when shown. If {@code false}, the dialog is {@code MODELESS}; 420 * if {@code true}, the modality type property is set to 421 * {@code DEFAULT_MODALITY_TYPE} 422 * @param gc the {@code GraphicsConfiguration} of the target screen device; 423 * if {@code null}, the default system {@code GraphicsConfiguration} 424 * is assumed 425 * @exception java.lang.IllegalArgumentException if {@code gc} 426 * is not from a screen device 427 * @exception HeadlessException when 428 * {@code GraphicsEnvironment.isHeadless()} returns {@code true} 429 * 430 * @see java.awt.Dialog.ModalityType 431 * @see java.awt.Dialog.ModalityType#MODELESS 432 * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE 433 * @see java.awt.Dialog#setModal 434 * @see java.awt.Dialog#setModalityType 435 * @see java.awt.GraphicsEnvironment#isHeadless 436 * @see Component#setSize 437 * @see Component#setVisible 438 * @since 1.4 439 */ Dialog(Frame owner, String title, boolean modal, GraphicsConfiguration gc)440 public Dialog(Frame owner, String title, boolean modal, 441 GraphicsConfiguration gc) { 442 this(owner, title, modal ? DEFAULT_MODALITY_TYPE : ModalityType.MODELESS, gc); 443 } 444 445 /** 446 * Constructs an initially invisible, modeless {@code Dialog} with 447 * the specified owner {@code Dialog} and an empty title. 448 * 449 * @param owner the owner of the dialog or {@code null} if this 450 * dialog has no owner 451 * @exception java.lang.IllegalArgumentException if the {@code owner}'s 452 * {@code GraphicsConfiguration} is not from a screen device 453 * @exception HeadlessException when 454 * {@code GraphicsEnvironment.isHeadless()} returns {@code true} 455 * @see java.awt.GraphicsEnvironment#isHeadless 456 * @since 1.2 457 */ Dialog(Dialog owner)458 public Dialog(Dialog owner) { 459 this(owner, "", false); 460 } 461 462 /** 463 * Constructs an initially invisible, modeless {@code Dialog} 464 * with the specified owner {@code Dialog} and title. 465 * 466 * @param owner the owner of the dialog or {@code null} if this 467 * has no owner 468 * @param title the title of the dialog or {@code null} if this dialog 469 * has no title 470 * @exception java.lang.IllegalArgumentException if the {@code owner}'s 471 * {@code GraphicsConfiguration} is not from a screen device 472 * @exception HeadlessException when 473 * {@code GraphicsEnvironment.isHeadless()} returns {@code true} 474 * 475 * @see java.awt.GraphicsEnvironment#isHeadless 476 * @since 1.2 477 */ Dialog(Dialog owner, String title)478 public Dialog(Dialog owner, String title) { 479 this(owner, title, false); 480 } 481 482 /** 483 * Constructs an initially invisible {@code Dialog} with the 484 * specified owner {@code Dialog}, title, and modality. 485 * 486 * @param owner the owner of the dialog or {@code null} if this 487 * dialog has no owner 488 * @param title the title of the dialog or {@code null} if this 489 * dialog has no title 490 * @param modal specifies whether dialog blocks user input to other top-level 491 * windows when shown. If {@code false}, the dialog is {@code MODELESS}; 492 * if {@code true}, the modality type property is set to 493 * {@code DEFAULT_MODALITY_TYPE} 494 * @exception IllegalArgumentException if the {@code owner}'s 495 * {@code GraphicsConfiguration} is not from a screen device 496 * @exception HeadlessException when 497 * {@code GraphicsEnvironment.isHeadless()} returns {@code true} 498 * 499 * @see java.awt.Dialog.ModalityType 500 * @see java.awt.Dialog.ModalityType#MODELESS 501 * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE 502 * @see java.awt.Dialog#setModal 503 * @see java.awt.Dialog#setModalityType 504 * @see java.awt.GraphicsEnvironment#isHeadless 505 * 506 * @since 1.2 507 */ Dialog(Dialog owner, String title, boolean modal)508 public Dialog(Dialog owner, String title, boolean modal) { 509 this(owner, title, modal ? DEFAULT_MODALITY_TYPE : ModalityType.MODELESS); 510 } 511 512 /** 513 * Constructs an initially invisible {@code Dialog} with the 514 * specified owner {@code Dialog}, title, modality and 515 * {@code GraphicsConfiguration}. 516 * 517 * @param owner the owner of the dialog or {@code null} if this 518 * dialog has no owner 519 * @param title the title of the dialog or {@code null} if this 520 * dialog has no title 521 * @param modal specifies whether dialog blocks user input to other top-level 522 * windows when shown. If {@code false}, the dialog is {@code MODELESS}; 523 * if {@code true}, the modality type property is set to 524 * {@code DEFAULT_MODALITY_TYPE} 525 * @param gc the {@code GraphicsConfiguration} of the target screen device; 526 * if {@code null}, the default system {@code GraphicsConfiguration} 527 * is assumed 528 * @exception java.lang.IllegalArgumentException if {@code gc} 529 * is not from a screen device 530 * @exception HeadlessException when 531 * {@code GraphicsEnvironment.isHeadless()} returns {@code true} 532 * 533 * @see java.awt.Dialog.ModalityType 534 * @see java.awt.Dialog.ModalityType#MODELESS 535 * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE 536 * @see java.awt.Dialog#setModal 537 * @see java.awt.Dialog#setModalityType 538 * @see java.awt.GraphicsEnvironment#isHeadless 539 * @see Component#setSize 540 * @see Component#setVisible 541 * 542 * @since 1.4 543 */ Dialog(Dialog owner, String title, boolean modal, GraphicsConfiguration gc)544 public Dialog(Dialog owner, String title, boolean modal, 545 GraphicsConfiguration gc) { 546 this(owner, title, modal ? DEFAULT_MODALITY_TYPE : ModalityType.MODELESS, gc); 547 } 548 549 /** 550 * Constructs an initially invisible, modeless {@code Dialog} with the 551 * specified owner {@code Window} and an empty title. 552 * 553 * @param owner the owner of the dialog. The owner must be an instance of 554 * {@link java.awt.Dialog Dialog}, {@link java.awt.Frame Frame}, any 555 * of their descendants or {@code null} 556 * 557 * @exception java.lang.IllegalArgumentException if the {@code owner} 558 * is not an instance of {@link java.awt.Dialog Dialog} or {@link 559 * java.awt.Frame Frame} 560 * @exception java.lang.IllegalArgumentException if the {@code owner}'s 561 * {@code GraphicsConfiguration} is not from a screen device 562 * @exception HeadlessException when 563 * {@code GraphicsEnvironment.isHeadless()} returns {@code true} 564 * 565 * @see java.awt.GraphicsEnvironment#isHeadless 566 * 567 * @since 1.6 568 */ Dialog(Window owner)569 public Dialog(Window owner) { 570 this(owner, "", ModalityType.MODELESS); 571 } 572 573 /** 574 * Constructs an initially invisible, modeless {@code Dialog} with 575 * the specified owner {@code Window} and title. 576 * 577 * @param owner the owner of the dialog. The owner must be an instance of 578 * {@link java.awt.Dialog Dialog}, {@link java.awt.Frame Frame}, any 579 * of their descendants or {@code null} 580 * @param title the title of the dialog or {@code null} if this dialog 581 * has no title 582 * 583 * @exception java.lang.IllegalArgumentException if the {@code owner} 584 * is not an instance of {@link java.awt.Dialog Dialog} or {@link 585 * java.awt.Frame Frame} 586 * @exception java.lang.IllegalArgumentException if the {@code owner}'s 587 * {@code GraphicsConfiguration} is not from a screen device 588 * @exception HeadlessException when 589 * {@code GraphicsEnvironment.isHeadless()} returns {@code true} 590 * 591 * @see java.awt.GraphicsEnvironment#isHeadless 592 * 593 * @since 1.6 594 */ Dialog(Window owner, String title)595 public Dialog(Window owner, String title) { 596 this(owner, title, ModalityType.MODELESS); 597 } 598 599 /** 600 * Constructs an initially invisible {@code Dialog} with the 601 * specified owner {@code Window} and modality and an empty title. 602 * 603 * @param owner the owner of the dialog. The owner must be an instance of 604 * {@link java.awt.Dialog Dialog}, {@link java.awt.Frame Frame}, any 605 * of their descendants or {@code null} 606 * @param modalityType specifies whether dialog blocks input to other 607 * windows when shown. {@code null} value and unsupported modality 608 * types are equivalent to {@code MODELESS} 609 * 610 * @exception java.lang.IllegalArgumentException if the {@code owner} 611 * is not an instance of {@link java.awt.Dialog Dialog} or {@link 612 * java.awt.Frame Frame} 613 * @exception java.lang.IllegalArgumentException if the {@code owner}'s 614 * {@code GraphicsConfiguration} is not from a screen device 615 * @exception HeadlessException when 616 * {@code GraphicsEnvironment.isHeadless()} returns {@code true} 617 * @exception SecurityException if the calling thread does not have permission 618 * to create modal dialogs with the given {@code modalityType} 619 * 620 * @see java.awt.Dialog.ModalityType 621 * @see java.awt.Dialog#setModal 622 * @see java.awt.Dialog#setModalityType 623 * @see java.awt.GraphicsEnvironment#isHeadless 624 * @see java.awt.Toolkit#isModalityTypeSupported 625 * 626 * @since 1.6 627 */ Dialog(Window owner, ModalityType modalityType)628 public Dialog(Window owner, ModalityType modalityType) { 629 this(owner, "", modalityType); 630 } 631 632 /** 633 * Constructs an initially invisible {@code Dialog} with the 634 * specified owner {@code Window}, title and modality. 635 * 636 * @param owner the owner of the dialog. The owner must be an instance of 637 * {@link java.awt.Dialog Dialog}, {@link java.awt.Frame Frame}, any 638 * of their descendants or {@code null} 639 * @param title the title of the dialog or {@code null} if this dialog 640 * has no title 641 * @param modalityType specifies whether dialog blocks input to other 642 * windows when shown. {@code null} value and unsupported modality 643 * types are equivalent to {@code MODELESS} 644 * 645 * @exception java.lang.IllegalArgumentException if the {@code owner} 646 * is not an instance of {@link java.awt.Dialog Dialog} or {@link 647 * java.awt.Frame Frame} 648 * @exception java.lang.IllegalArgumentException if the {@code owner}'s 649 * {@code GraphicsConfiguration} is not from a screen device 650 * @exception HeadlessException when 651 * {@code GraphicsEnvironment.isHeadless()} returns {@code true} 652 * @exception SecurityException if the calling thread does not have permission 653 * to create modal dialogs with the given {@code modalityType} 654 * 655 * @see java.awt.Dialog.ModalityType 656 * @see java.awt.Dialog#setModal 657 * @see java.awt.Dialog#setModalityType 658 * @see java.awt.GraphicsEnvironment#isHeadless 659 * @see java.awt.Toolkit#isModalityTypeSupported 660 * 661 * @since 1.6 662 */ Dialog(Window owner, String title, ModalityType modalityType)663 public Dialog(Window owner, String title, ModalityType modalityType) { 664 super(owner); 665 666 if ((owner != null) && 667 !(owner instanceof Frame) && 668 !(owner instanceof Dialog)) 669 { 670 throw new IllegalArgumentException("Wrong parent window"); 671 } 672 673 this.title = title; 674 setModalityType(modalityType); 675 SunToolkit.checkAndSetPolicy(this); 676 initialized = true; 677 } 678 679 /** 680 * Constructs an initially invisible {@code Dialog} with the 681 * specified owner {@code Window}, title, modality and 682 * {@code GraphicsConfiguration}. 683 * 684 * @param owner the owner of the dialog. The owner must be an instance of 685 * {@link java.awt.Dialog Dialog}, {@link java.awt.Frame Frame}, any 686 * of their descendants or {@code null} 687 * @param title the title of the dialog or {@code null} if this dialog 688 * has no title 689 * @param modalityType specifies whether dialog blocks input to other 690 * windows when shown. {@code null} value and unsupported modality 691 * types are equivalent to {@code MODELESS} 692 * @param gc the {@code GraphicsConfiguration} of the target screen device; 693 * if {@code null}, the default system {@code GraphicsConfiguration} 694 * is assumed 695 * 696 * @exception java.lang.IllegalArgumentException if the {@code owner} 697 * is not an instance of {@link java.awt.Dialog Dialog} or {@link 698 * java.awt.Frame Frame} 699 * @exception java.lang.IllegalArgumentException if {@code gc} 700 * is not from a screen device 701 * @exception HeadlessException when 702 * {@code GraphicsEnvironment.isHeadless()} returns {@code true} 703 * @exception SecurityException if the calling thread does not have permission 704 * to create modal dialogs with the given {@code modalityType} 705 * 706 * @see java.awt.Dialog.ModalityType 707 * @see java.awt.Dialog#setModal 708 * @see java.awt.Dialog#setModalityType 709 * @see java.awt.GraphicsEnvironment#isHeadless 710 * @see java.awt.Toolkit#isModalityTypeSupported 711 * 712 * @since 1.6 713 */ Dialog(Window owner, String title, ModalityType modalityType, GraphicsConfiguration gc)714 public Dialog(Window owner, String title, ModalityType modalityType, 715 GraphicsConfiguration gc) { 716 super(owner, gc); 717 718 if ((owner != null) && 719 !(owner instanceof Frame) && 720 !(owner instanceof Dialog)) 721 { 722 throw new IllegalArgumentException("wrong owner window"); 723 } 724 725 this.title = title; 726 setModalityType(modalityType); 727 SunToolkit.checkAndSetPolicy(this); 728 initialized = true; 729 } 730 731 /** 732 * Construct a name for this component. Called by getName() when the 733 * name is null. 734 */ constructComponentName()735 String constructComponentName() { 736 synchronized (Dialog.class) { 737 return base + nameCounter++; 738 } 739 } 740 741 /** 742 * Makes this Dialog displayable by connecting it to 743 * a native screen resource. Making a dialog displayable will 744 * cause any of its children to be made displayable. 745 * This method is called internally by the toolkit and should 746 * not be called directly by programs. 747 * @see Component#isDisplayable 748 * @see #removeNotify 749 */ addNotify()750 public void addNotify() { 751 synchronized (getTreeLock()) { 752 if (parent != null && parent.peer == null) { 753 parent.addNotify(); 754 } 755 756 if (peer == null) { 757 peer = getComponentFactory().createDialog(this); 758 } 759 super.addNotify(); 760 } 761 } 762 763 /** 764 * Indicates whether the dialog is modal. 765 * <p> 766 * This method is obsolete and is kept for backwards compatibility only. 767 * Use {@link #getModalityType getModalityType()} instead. 768 * 769 * @return {@code true} if this dialog window is modal; 770 * {@code false} otherwise 771 * 772 * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE 773 * @see java.awt.Dialog.ModalityType#MODELESS 774 * @see java.awt.Dialog#setModal 775 * @see java.awt.Dialog#getModalityType 776 * @see java.awt.Dialog#setModalityType 777 */ isModal()778 public boolean isModal() { 779 return isModal_NoClientCode(); 780 } isModal_NoClientCode()781 final boolean isModal_NoClientCode() { 782 return modalityType != ModalityType.MODELESS; 783 } 784 785 /** 786 * Specifies whether this dialog should be modal. 787 * <p> 788 * This method is obsolete and is kept for backwards compatibility only. 789 * Use {@link #setModalityType setModalityType()} instead. 790 * <p> 791 * Note: changing modality of the visible dialog may have no effect 792 * until it is hidden and then shown again. 793 * 794 * @param modal specifies whether dialog blocks input to other windows 795 * when shown; calling to {@code setModal(true)} is equivalent to 796 * {@code setModalityType(Dialog.DEFAULT_MODALITY_TYPE)}, and 797 * calling to {@code setModal(false)} is equivalent to 798 * {@code setModalityType(Dialog.ModalityType.MODELESS)} 799 * 800 * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE 801 * @see java.awt.Dialog.ModalityType#MODELESS 802 * @see java.awt.Dialog#isModal 803 * @see java.awt.Dialog#getModalityType 804 * @see java.awt.Dialog#setModalityType 805 * 806 * @since 1.1 807 */ setModal(boolean modal)808 public void setModal(boolean modal) { 809 this.modal = modal; 810 setModalityType(modal ? DEFAULT_MODALITY_TYPE : ModalityType.MODELESS); 811 } 812 813 /** 814 * Returns the modality type of this dialog. 815 * 816 * @return modality type of this dialog 817 * 818 * @see java.awt.Dialog#setModalityType 819 * 820 * @since 1.6 821 */ getModalityType()822 public ModalityType getModalityType() { 823 return modalityType; 824 } 825 826 /** 827 * Sets the modality type for this dialog. See {@link 828 * java.awt.Dialog.ModalityType ModalityType} for possible modality types. 829 * <p> 830 * If the given modality type is not supported, {@code MODELESS} 831 * is used. You may want to call {@code getModalityType()} after calling 832 * this method to ensure that the modality type has been set. 833 * <p> 834 * Note: changing modality of the visible dialog may have no effect 835 * until it is hidden and then shown again. 836 * 837 * @param type specifies whether dialog blocks input to other 838 * windows when shown. {@code null} value and unsupported modality 839 * types are equivalent to {@code MODELESS} 840 * @exception SecurityException if the calling thread does not have permission 841 * to create modal dialogs with the given {@code modalityType} 842 * 843 * @see java.awt.Dialog#getModalityType 844 * @see java.awt.Toolkit#isModalityTypeSupported 845 * 846 * @since 1.6 847 */ setModalityType(ModalityType type)848 public void setModalityType(ModalityType type) { 849 if (type == null) { 850 type = Dialog.ModalityType.MODELESS; 851 } 852 if (!Toolkit.getDefaultToolkit().isModalityTypeSupported(type)) { 853 type = Dialog.ModalityType.MODELESS; 854 } 855 if (modalityType == type) { 856 return; 857 } 858 859 checkModalityPermission(type); 860 861 modalityType = type; 862 modal = (modalityType != ModalityType.MODELESS); 863 } 864 865 /** 866 * Gets the title of the dialog. The title is displayed in the 867 * dialog's border. 868 * @return the title of this dialog window. The title may be 869 * {@code null}. 870 * @see java.awt.Dialog#setTitle 871 */ getTitle()872 public String getTitle() { 873 return title; 874 } 875 876 /** 877 * Sets the title of the Dialog. 878 * @param title the title displayed in the dialog's border; 879 * a null value results in an empty title 880 * @see #getTitle 881 */ setTitle(String title)882 public void setTitle(String title) { 883 String oldTitle = this.title; 884 885 synchronized(this) { 886 this.title = title; 887 DialogPeer peer = (DialogPeer)this.peer; 888 if (peer != null) { 889 peer.setTitle(title); 890 } 891 } 892 firePropertyChange("title", oldTitle, title); 893 } 894 895 /** 896 * @return true if we actually showed, false if we just called toFront() 897 */ 898 @SuppressWarnings("deprecation") conditionalShow(Component toFocus, AtomicLong time)899 private boolean conditionalShow(Component toFocus, AtomicLong time) { 900 boolean retval; 901 902 closeSplashScreen(); 903 904 synchronized (getTreeLock()) { 905 if (peer == null) { 906 addNotify(); 907 } 908 validateUnconditionally(); 909 if (visible) { 910 toFront(); 911 retval = false; 912 } else { 913 visible = retval = true; 914 915 // check if this dialog should be modal blocked BEFORE calling peer.show(), 916 // otherwise, a pair of FOCUS_GAINED and FOCUS_LOST may be mistakenly 917 // generated for the dialog 918 if (!isModal()) { 919 checkShouldBeBlocked(this); 920 } else { 921 modalDialogs.add(this); 922 modalShow(); 923 } 924 925 if (toFocus != null && time != null && isFocusable() && 926 isEnabled() && !isModalBlocked()) { 927 // keep the KeyEvents from being dispatched 928 // until the focus has been transferred 929 time.set(Toolkit.getEventQueue().getMostRecentKeyEventTime()); 930 KeyboardFocusManager.getCurrentKeyboardFocusManager(). 931 enqueueKeyEvents(time.get(), toFocus); 932 } 933 934 // This call is required as the show() method of the Dialog class 935 // does not invoke the super.show(). So wried... :( 936 mixOnShowing(); 937 938 peer.setVisible(true); // now guaranteed never to block 939 if (isModalBlocked()) { 940 modalBlocker.toFront(); 941 } 942 943 setLocationByPlatform(false); 944 for (int i = 0; i < ownedWindowList.size(); i++) { 945 Window child = ownedWindowList.elementAt(i).get(); 946 if ((child != null) && child.showWithParent) { 947 child.show(); 948 child.showWithParent = false; 949 } // endif 950 } // endfor 951 Window.updateChildFocusableWindowState(this); 952 953 createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, 954 this, parent, 955 HierarchyEvent.SHOWING_CHANGED, 956 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); 957 if (componentListener != null || 958 (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0 || 959 Toolkit.enabledOnToolkit(AWTEvent.COMPONENT_EVENT_MASK)) { 960 ComponentEvent e = 961 new ComponentEvent(this, ComponentEvent.COMPONENT_SHOWN); 962 Toolkit.getEventQueue().postEvent(e); 963 } 964 } 965 } 966 967 if (retval && (state & OPENED) == 0) { 968 postWindowEvent(WindowEvent.WINDOW_OPENED); 969 state |= OPENED; 970 } 971 972 return retval; 973 } 974 975 /** 976 * Shows or hides this {@code Dialog} depending on the value of parameter 977 * {@code b}. 978 * @param b if {@code true}, makes the {@code Dialog} visible, 979 * otherwise hides the {@code Dialog}. 980 * If the dialog and/or its owner 981 * are not yet displayable, both are made displayable. The 982 * dialog will be validated prior to being made visible. 983 * If {@code false}, hides the {@code Dialog} and then causes {@code setVisible(true)} 984 * to return if it is currently blocked. 985 * <p> 986 * <b>Notes for modal dialogs</b>. 987 * <ul> 988 * <li>{@code setVisible(true)}: If the dialog is not already 989 * visible, this call will not return until the dialog is 990 * hidden by calling {@code setVisible(false)} or 991 * {@code dispose}. 992 * <li>{@code setVisible(false)}: Hides the dialog and then 993 * returns on {@code setVisible(true)} if it is currently blocked. 994 * <li>It is OK to call this method from the event dispatching 995 * thread because the toolkit ensures that other events are 996 * not blocked while this method is blocked. 997 * </ul> 998 * @see java.awt.Window#setVisible 999 * @see java.awt.Window#dispose 1000 * @see java.awt.Component#isDisplayable 1001 * @see java.awt.Component#validate 1002 * @see java.awt.Dialog#isModal 1003 */ setVisible(boolean b)1004 public void setVisible(boolean b) { 1005 super.setVisible(b); 1006 } 1007 1008 /** 1009 * Makes the {@code Dialog} visible. If the dialog and/or its owner 1010 * are not yet displayable, both are made displayable. The 1011 * dialog will be validated prior to being made visible. 1012 * If the dialog is already visible, this will bring the dialog 1013 * to the front. 1014 * <p> 1015 * If the dialog is modal and is not already visible, this call 1016 * will not return until the dialog is hidden by calling hide or 1017 * dispose. It is permissible to show modal dialogs from the event 1018 * dispatching thread because the toolkit will ensure that another 1019 * event pump runs while the one which invoked this method is blocked. 1020 * @see Component#hide 1021 * @see Component#isDisplayable 1022 * @see Component#validate 1023 * @see #isModal 1024 * @see Window#setVisible(boolean) 1025 * @deprecated As of JDK version 1.5, replaced by 1026 * {@link #setVisible(boolean) setVisible(boolean)}. 1027 */ 1028 @Deprecated show()1029 public void show() { 1030 if (!initialized) { 1031 throw new IllegalStateException("The dialog component " + 1032 "has not been initialized properly"); 1033 } 1034 1035 beforeFirstShow = false; 1036 if (!isModal()) { 1037 conditionalShow(null, null); 1038 } else { 1039 AppContext showAppContext = AppContext.getAppContext(); 1040 1041 AtomicLong time = new AtomicLong(); 1042 Component predictedFocusOwner = null; 1043 try { 1044 predictedFocusOwner = getMostRecentFocusOwner(); 1045 if (conditionalShow(predictedFocusOwner, time)) { 1046 modalFilter = ModalEventFilter.createFilterForDialog(this); 1047 // if this dialog is toolkit-modal, the filter should be added 1048 // to all EDTs (for all AppContexts) 1049 if (modalityType == ModalityType.TOOLKIT_MODAL) { 1050 Iterator<AppContext> it = AppContext.getAppContexts().iterator(); 1051 while (it.hasNext()) { 1052 AppContext appContext = it.next(); 1053 if (appContext == showAppContext) { 1054 continue; 1055 } 1056 EventQueue eventQueue = (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY); 1057 // it may occur that EDT for appContext hasn't been started yet, so 1058 // we post an empty invocation event to trigger EDT initialization 1059 eventQueue.postEvent(new InvocationEvent(this, () -> {})); 1060 EventDispatchThread edt = eventQueue.getDispatchThread(); 1061 edt.addEventFilter(modalFilter); 1062 } 1063 } 1064 1065 modalityPushed(); 1066 try { 1067 final EventQueue eventQueue = AccessController.doPrivileged( 1068 (PrivilegedAction<EventQueue>) Toolkit.getDefaultToolkit()::getSystemEventQueue); 1069 secondaryLoop = eventQueue.createSecondaryLoop(() -> true, modalFilter, 0); 1070 if (!secondaryLoop.enter()) { 1071 secondaryLoop = null; 1072 } 1073 } finally { 1074 modalityPopped(); 1075 } 1076 1077 // if this dialog is toolkit-modal, its filter must be removed 1078 // from all EDTs (for all AppContexts) 1079 if (modalityType == ModalityType.TOOLKIT_MODAL) { 1080 Iterator<AppContext> it = AppContext.getAppContexts().iterator(); 1081 while (it.hasNext()) { 1082 AppContext appContext = it.next(); 1083 if (appContext == showAppContext) { 1084 continue; 1085 } 1086 EventQueue eventQueue = (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY); 1087 EventDispatchThread edt = eventQueue.getDispatchThread(); 1088 edt.removeEventFilter(modalFilter); 1089 } 1090 } 1091 } 1092 } finally { 1093 if (predictedFocusOwner != null) { 1094 // Restore normal key event dispatching 1095 KeyboardFocusManager.getCurrentKeyboardFocusManager(). 1096 dequeueKeyEvents(time.get(), predictedFocusOwner); 1097 } 1098 } 1099 } 1100 } 1101 modalityPushed()1102 final void modalityPushed() { 1103 Toolkit tk = Toolkit.getDefaultToolkit(); 1104 if (tk instanceof SunToolkit) { 1105 SunToolkit stk = (SunToolkit)tk; 1106 stk.notifyModalityPushed(this); 1107 } 1108 } 1109 modalityPopped()1110 final void modalityPopped() { 1111 Toolkit tk = Toolkit.getDefaultToolkit(); 1112 if (tk instanceof SunToolkit) { 1113 SunToolkit stk = (SunToolkit)tk; 1114 stk.notifyModalityPopped(this); 1115 } 1116 } 1117 hideAndDisposePreHandler()1118 private void hideAndDisposePreHandler() { 1119 isInHide = true; 1120 synchronized (getTreeLock()) { 1121 if (secondaryLoop != null) { 1122 modalHide(); 1123 // dialog can be shown and then disposed before its 1124 // modal filter is created 1125 if (modalFilter != null) { 1126 modalFilter.disable(); 1127 } 1128 modalDialogs.remove(this); 1129 } 1130 } 1131 } hideAndDisposeHandler()1132 private void hideAndDisposeHandler() { 1133 if (secondaryLoop != null) { 1134 secondaryLoop.exit(); 1135 secondaryLoop = null; 1136 } 1137 isInHide = false; 1138 } 1139 1140 /** 1141 * Hides the Dialog and then causes {@code show} to return if it is currently 1142 * blocked. 1143 * @see Window#show 1144 * @see Window#dispose 1145 * @see Window#setVisible(boolean) 1146 * @deprecated As of JDK version 1.5, replaced by 1147 * {@link #setVisible(boolean) setVisible(boolean)}. 1148 */ 1149 @Deprecated hide()1150 public void hide() { 1151 hideAndDisposePreHandler(); 1152 super.hide(); 1153 // fix for 5048370: if hide() is called from super.doDispose(), then 1154 // hideAndDisposeHandler() should not be called here as it will be called 1155 // at the end of doDispose() 1156 if (!isInDispose) { 1157 hideAndDisposeHandler(); 1158 } 1159 } 1160 1161 /** 1162 * Disposes the Dialog and then causes show() to return if it is currently 1163 * blocked. 1164 */ doDispose()1165 void doDispose() { 1166 // fix for 5048370: set isInDispose flag to true to prevent calling 1167 // to hideAndDisposeHandler() from hide() 1168 isInDispose = true; 1169 super.doDispose(); 1170 hideAndDisposeHandler(); 1171 isInDispose = false; 1172 } 1173 1174 /** 1175 * {@inheritDoc} 1176 * <p> 1177 * If this dialog is modal and blocks some windows, then all of them are 1178 * also sent to the back to keep them below the blocking dialog. 1179 * 1180 * @see java.awt.Window#toBack 1181 */ toBack()1182 public void toBack() { 1183 super.toBack(); 1184 if (visible) { 1185 synchronized (getTreeLock()) { 1186 for (Window w : blockedWindows) { 1187 w.toBack_NoClientCode(); 1188 } 1189 } 1190 } 1191 } 1192 1193 /** 1194 * Indicates whether this dialog is resizable by the user. 1195 * By default, all dialogs are initially resizable. 1196 * @return {@code true} if the user can resize the dialog; 1197 * {@code false} otherwise. 1198 * @see java.awt.Dialog#setResizable 1199 */ isResizable()1200 public boolean isResizable() { 1201 return resizable; 1202 } 1203 1204 /** 1205 * Sets whether this dialog is resizable by the user. 1206 * @param resizable {@code true} if the user can 1207 * resize this dialog; {@code false} otherwise. 1208 * @see java.awt.Dialog#isResizable 1209 */ setResizable(boolean resizable)1210 public void setResizable(boolean resizable) { 1211 boolean testvalid = false; 1212 1213 synchronized (this) { 1214 this.resizable = resizable; 1215 DialogPeer peer = (DialogPeer)this.peer; 1216 if (peer != null) { 1217 peer.setResizable(resizable); 1218 testvalid = true; 1219 } 1220 } 1221 1222 // On some platforms, changing the resizable state affects 1223 // the insets of the Dialog. If we could, we'd call invalidate() 1224 // from the peer, but we need to guarantee that we're not holding 1225 // the Dialog lock when we call invalidate(). 1226 if (testvalid) { 1227 invalidateIfValid(); 1228 } 1229 } 1230 1231 1232 /** 1233 * Disables or enables decorations for this dialog. 1234 * <p> 1235 * This method can only be called while the dialog is not displayable. To 1236 * make this dialog decorated, it must be opaque and have the default shape, 1237 * otherwise the {@code IllegalComponentStateException} will be thrown. 1238 * Refer to {@link Window#setShape}, {@link Window#setOpacity} and {@link 1239 * Window#setBackground} for details 1240 * 1241 * @param undecorated {@code true} if no dialog decorations are to be 1242 * enabled; {@code false} if dialog decorations are to be enabled 1243 * 1244 * @throws IllegalComponentStateException if the dialog is displayable 1245 * @throws IllegalComponentStateException if {@code undecorated} is 1246 * {@code false}, and this dialog does not have the default shape 1247 * @throws IllegalComponentStateException if {@code undecorated} is 1248 * {@code false}, and this dialog opacity is less than {@code 1.0f} 1249 * @throws IllegalComponentStateException if {@code undecorated} is 1250 * {@code false}, and the alpha value of this dialog background 1251 * color is less than {@code 1.0f} 1252 * 1253 * @see #isUndecorated 1254 * @see Component#isDisplayable 1255 * @see Window#getShape 1256 * @see Window#getOpacity 1257 * @see Window#getBackground 1258 * 1259 * @since 1.4 1260 */ setUndecorated(boolean undecorated)1261 public void setUndecorated(boolean undecorated) { 1262 /* Make sure we don't run in the middle of peer creation.*/ 1263 synchronized (getTreeLock()) { 1264 if (isDisplayable()) { 1265 throw new IllegalComponentStateException("The dialog is displayable."); 1266 } 1267 if (!undecorated) { 1268 if (getOpacity() < 1.0f) { 1269 throw new IllegalComponentStateException("The dialog is not opaque"); 1270 } 1271 if (getShape() != null) { 1272 throw new IllegalComponentStateException("The dialog does not have a default shape"); 1273 } 1274 Color bg = getBackground(); 1275 if ((bg != null) && (bg.getAlpha() < 255)) { 1276 throw new IllegalComponentStateException("The dialog background color is not opaque"); 1277 } 1278 } 1279 this.undecorated = undecorated; 1280 } 1281 } 1282 1283 /** 1284 * Indicates whether this dialog is undecorated. 1285 * By default, all dialogs are initially decorated. 1286 * @return {@code true} if dialog is undecorated; 1287 * {@code false} otherwise. 1288 * @see java.awt.Dialog#setUndecorated 1289 * @since 1.4 1290 */ isUndecorated()1291 public boolean isUndecorated() { 1292 return undecorated; 1293 } 1294 1295 /** 1296 * {@inheritDoc} 1297 */ 1298 @Override setOpacity(float opacity)1299 public void setOpacity(float opacity) { 1300 synchronized (getTreeLock()) { 1301 if ((opacity < 1.0f) && !isUndecorated()) { 1302 throw new IllegalComponentStateException("The dialog is decorated"); 1303 } 1304 super.setOpacity(opacity); 1305 } 1306 } 1307 1308 /** 1309 * {@inheritDoc} 1310 */ 1311 @Override setShape(Shape shape)1312 public void setShape(Shape shape) { 1313 synchronized (getTreeLock()) { 1314 if ((shape != null) && !isUndecorated()) { 1315 throw new IllegalComponentStateException("The dialog is decorated"); 1316 } 1317 super.setShape(shape); 1318 } 1319 } 1320 1321 /** 1322 * {@inheritDoc} 1323 */ 1324 @Override setBackground(Color bgColor)1325 public void setBackground(Color bgColor) { 1326 synchronized (getTreeLock()) { 1327 if ((bgColor != null) && (bgColor.getAlpha() < 255) && !isUndecorated()) { 1328 throw new IllegalComponentStateException("The dialog is decorated"); 1329 } 1330 super.setBackground(bgColor); 1331 } 1332 } 1333 1334 /** 1335 * Returns a string representing the state of this dialog. This 1336 * method is intended to be used only for debugging purposes, and the 1337 * content and format of the returned string may vary between 1338 * implementations. The returned string may be empty but may not be 1339 * {@code null}. 1340 * 1341 * @return the parameter string of this dialog window. 1342 */ paramString()1343 protected String paramString() { 1344 String str = super.paramString() + "," + modalityType; 1345 if (title != null) { 1346 str += ",title=" + title; 1347 } 1348 return str; 1349 } 1350 1351 /** 1352 * Initialize JNI field and method IDs 1353 */ initIDs()1354 private static native void initIDs(); 1355 1356 /* 1357 * --- Modality support --- 1358 * 1359 */ 1360 1361 /* 1362 * This method is called only for modal dialogs. 1363 * 1364 * Goes through the list of all visible top-level windows and 1365 * divide them into three distinct groups: blockers of this dialog, 1366 * blocked by this dialog and all others. Then blocks this dialog 1367 * by first met dialog from the first group (if any) and blocks all 1368 * the windows from the second group. 1369 */ modalShow()1370 void modalShow() { 1371 // find all the dialogs that block this one 1372 IdentityArrayList<Dialog> blockers = new IdentityArrayList<Dialog>(); 1373 for (Dialog d : modalDialogs) { 1374 if (d.shouldBlock(this)) { 1375 Window w = d; 1376 while ((w != null) && (w != this)) { 1377 w = w.getOwner_NoClientCode(); 1378 } 1379 if ((w == this) || !shouldBlock(d) || (modalityType.compareTo(d.getModalityType()) < 0)) { 1380 blockers.add(d); 1381 } 1382 } 1383 } 1384 1385 // add all blockers' blockers to blockers :) 1386 for (int i = 0; i < blockers.size(); i++) { 1387 Dialog blocker = blockers.get(i); 1388 if (blocker.isModalBlocked()) { 1389 Dialog blockerBlocker = blocker.getModalBlocker(); 1390 if (!blockers.contains(blockerBlocker)) { 1391 blockers.add(i + 1, blockerBlocker); 1392 } 1393 } 1394 } 1395 1396 if (blockers.size() > 0) { 1397 blockers.get(0).blockWindow(this); 1398 } 1399 1400 // find all windows from blockers' hierarchies 1401 IdentityArrayList<Window> blockersHierarchies = new IdentityArrayList<Window>(blockers); 1402 int k = 0; 1403 while (k < blockersHierarchies.size()) { 1404 Window w = blockersHierarchies.get(k); 1405 Window[] ownedWindows = w.getOwnedWindows_NoClientCode(); 1406 for (Window win : ownedWindows) { 1407 blockersHierarchies.add(win); 1408 } 1409 k++; 1410 } 1411 1412 java.util.List<Window> toBlock = new IdentityLinkedList<Window>(); 1413 // block all windows from scope of blocking except from blockers' hierarchies 1414 IdentityArrayList<Window> unblockedWindows = Window.getAllUnblockedWindows(); 1415 for (Window w : unblockedWindows) { 1416 if (shouldBlock(w) && !blockersHierarchies.contains(w)) { 1417 if ((w instanceof Dialog) && ((Dialog)w).isModal_NoClientCode()) { 1418 Dialog wd = (Dialog)w; 1419 if (wd.shouldBlock(this) && (modalDialogs.indexOf(wd) > modalDialogs.indexOf(this))) { 1420 continue; 1421 } 1422 } 1423 toBlock.add(w); 1424 } 1425 } 1426 blockWindows(toBlock); 1427 1428 if (!isModalBlocked()) { 1429 updateChildrenBlocking(); 1430 } 1431 } 1432 1433 /* 1434 * This method is called only for modal dialogs. 1435 * 1436 * Unblocks all the windows blocked by this modal dialog. After 1437 * each of them has been unblocked, it is checked to be blocked by 1438 * any other modal dialogs. 1439 */ modalHide()1440 void modalHide() { 1441 // we should unblock all the windows first... 1442 IdentityArrayList<Window> save = new IdentityArrayList<Window>(); 1443 int blockedWindowsCount = blockedWindows.size(); 1444 for (int i = 0; i < blockedWindowsCount; i++) { 1445 Window w = blockedWindows.get(0); 1446 save.add(w); 1447 unblockWindow(w); // also removes w from blockedWindows 1448 } 1449 // ... and only after that check if they should be blocked 1450 // by another dialogs 1451 for (int i = 0; i < blockedWindowsCount; i++) { 1452 Window w = save.get(i); 1453 if ((w instanceof Dialog) && ((Dialog)w).isModal_NoClientCode()) { 1454 Dialog d = (Dialog)w; 1455 d.modalShow(); 1456 } else { 1457 checkShouldBeBlocked(w); 1458 } 1459 } 1460 } 1461 1462 /* 1463 * Returns whether the given top-level window should be blocked by 1464 * this dialog. Note, that the given window can be also a modal dialog 1465 * and it should block this dialog, but this method do not take such 1466 * situations into consideration (such checks are performed in the 1467 * modalShow() and modalHide() methods). 1468 * 1469 * This method should be called on the getTreeLock() lock. 1470 */ shouldBlock(Window w)1471 boolean shouldBlock(Window w) { 1472 if (!isVisible_NoClientCode() || 1473 (!w.isVisible_NoClientCode() && !w.isInShow) || 1474 isInHide || 1475 (w == this) || 1476 !isModal_NoClientCode()) 1477 { 1478 return false; 1479 } 1480 if ((w instanceof Dialog) && ((Dialog)w).isInHide) { 1481 return false; 1482 } 1483 // check if w is from children hierarchy 1484 // fix for 6271546: we should also take into consideration child hierarchies 1485 // of this dialog's blockers 1486 Window blockerToCheck = this; 1487 while (blockerToCheck != null) { 1488 Component c = w; 1489 while ((c != null) && (c != blockerToCheck)) { 1490 c = c.getParent_NoClientCode(); 1491 } 1492 if (c == blockerToCheck) { 1493 return false; 1494 } 1495 blockerToCheck = blockerToCheck.getModalBlocker(); 1496 } 1497 switch (modalityType) { 1498 case MODELESS: 1499 return false; 1500 case DOCUMENT_MODAL: 1501 if (w.isModalExcluded(ModalExclusionType.APPLICATION_EXCLUDE)) { 1502 // application- and toolkit-excluded windows are not blocked by 1503 // document-modal dialogs from outside their children hierarchy 1504 Component c = this; 1505 while ((c != null) && (c != w)) { 1506 c = c.getParent_NoClientCode(); 1507 } 1508 return c == w; 1509 } else { 1510 return getDocumentRoot() == w.getDocumentRoot(); 1511 } 1512 case APPLICATION_MODAL: 1513 return !w.isModalExcluded(ModalExclusionType.APPLICATION_EXCLUDE) && 1514 (appContext == w.appContext); 1515 case TOOLKIT_MODAL: 1516 return !w.isModalExcluded(ModalExclusionType.TOOLKIT_EXCLUDE); 1517 } 1518 1519 return false; 1520 } 1521 1522 /* 1523 * Adds the given top-level window to the list of blocked 1524 * windows for this dialog and marks it as modal blocked. 1525 * If the window is already blocked by some modal dialog, 1526 * does nothing. 1527 */ blockWindow(Window w)1528 void blockWindow(Window w) { 1529 if (!w.isModalBlocked()) { 1530 w.setModalBlocked(this, true, true); 1531 blockedWindows.add(w); 1532 } 1533 } 1534 blockWindows(java.util.List<Window> toBlock)1535 void blockWindows(java.util.List<Window> toBlock) { 1536 DialogPeer dpeer = (DialogPeer)peer; 1537 if (dpeer == null) { 1538 return; 1539 } 1540 Iterator<Window> it = toBlock.iterator(); 1541 while (it.hasNext()) { 1542 Window w = it.next(); 1543 if (!w.isModalBlocked()) { 1544 w.setModalBlocked(this, true, false); 1545 } else { 1546 it.remove(); 1547 } 1548 } 1549 dpeer.blockWindows(toBlock); 1550 blockedWindows.addAll(toBlock); 1551 } 1552 1553 /* 1554 * Removes the given top-level window from the list of blocked 1555 * windows for this dialog and marks it as unblocked. If the 1556 * window is not modal blocked, does nothing. 1557 */ unblockWindow(Window w)1558 void unblockWindow(Window w) { 1559 if (w.isModalBlocked() && blockedWindows.contains(w)) { 1560 blockedWindows.remove(w); 1561 w.setModalBlocked(this, false, true); 1562 } 1563 } 1564 1565 /* 1566 * Checks if any other modal dialog D blocks the given window. 1567 * If such D exists, mark the window as blocked by D. 1568 */ checkShouldBeBlocked(Window w)1569 static void checkShouldBeBlocked(Window w) { 1570 synchronized (w.getTreeLock()) { 1571 for (int i = 0; i < modalDialogs.size(); i++) { 1572 Dialog modalDialog = modalDialogs.get(i); 1573 if (modalDialog.shouldBlock(w)) { 1574 modalDialog.blockWindow(w); 1575 break; 1576 } 1577 } 1578 } 1579 } 1580 checkModalityPermission(ModalityType mt)1581 private void checkModalityPermission(ModalityType mt) { 1582 if (mt == ModalityType.TOOLKIT_MODAL) { 1583 SecurityManager sm = System.getSecurityManager(); 1584 if (sm != null) { 1585 sm.checkPermission(AWTPermissions.TOOLKIT_MODALITY_PERMISSION); 1586 } 1587 } 1588 } 1589 readObject(ObjectInputStream s)1590 private void readObject(ObjectInputStream s) 1591 throws ClassNotFoundException, IOException, HeadlessException 1592 { 1593 GraphicsEnvironment.checkHeadless(); 1594 1595 java.io.ObjectInputStream.GetField fields = 1596 s.readFields(); 1597 1598 ModalityType localModalityType = (ModalityType)fields.get("modalityType", null); 1599 1600 try { 1601 checkModalityPermission(localModalityType); 1602 } catch (AccessControlException ace) { 1603 localModalityType = DEFAULT_MODALITY_TYPE; 1604 } 1605 1606 // in 1.5 or earlier modalityType was absent, so use "modal" instead 1607 if (localModalityType == null) { 1608 this.modal = fields.get("modal", false); 1609 setModal(modal); 1610 } else { 1611 this.modalityType = localModalityType; 1612 } 1613 1614 this.resizable = fields.get("resizable", true); 1615 this.undecorated = fields.get("undecorated", false); 1616 this.title = (String)fields.get("title", ""); 1617 1618 blockedWindows = new IdentityArrayList<>(); 1619 1620 SunToolkit.checkAndSetPolicy(this); 1621 1622 initialized = true; 1623 1624 } 1625 1626 /* 1627 * --- Accessibility Support --- 1628 * 1629 */ 1630 1631 /** 1632 * Gets the AccessibleContext associated with this Dialog. 1633 * For dialogs, the AccessibleContext takes the form of an 1634 * AccessibleAWTDialog. 1635 * A new AccessibleAWTDialog instance is created if necessary. 1636 * 1637 * @return an AccessibleAWTDialog that serves as the 1638 * AccessibleContext of this Dialog 1639 * @since 1.3 1640 */ getAccessibleContext()1641 public AccessibleContext getAccessibleContext() { 1642 if (accessibleContext == null) { 1643 accessibleContext = new AccessibleAWTDialog(); 1644 } 1645 return accessibleContext; 1646 } 1647 1648 /** 1649 * This class implements accessibility support for the 1650 * {@code Dialog} class. It provides an implementation of the 1651 * Java Accessibility API appropriate to dialog user-interface elements. 1652 * @since 1.3 1653 */ 1654 protected class AccessibleAWTDialog extends AccessibleAWTWindow 1655 { 1656 /* 1657 * JDK 1.3 serialVersionUID 1658 */ 1659 private static final long serialVersionUID = 4837230331833941201L; 1660 1661 /** 1662 * Get the role of this object. 1663 * 1664 * @return an instance of AccessibleRole describing the role of the 1665 * object 1666 * @see AccessibleRole 1667 */ getAccessibleRole()1668 public AccessibleRole getAccessibleRole() { 1669 return AccessibleRole.DIALOG; 1670 } 1671 1672 /** 1673 * Get the state of this object. 1674 * 1675 * @return an instance of AccessibleStateSet containing the current 1676 * state set of the object 1677 * @see AccessibleState 1678 */ getAccessibleStateSet()1679 public AccessibleStateSet getAccessibleStateSet() { 1680 AccessibleStateSet states = super.getAccessibleStateSet(); 1681 if (getFocusOwner() != null) { 1682 states.add(AccessibleState.ACTIVE); 1683 } 1684 if (isModal()) { 1685 states.add(AccessibleState.MODAL); 1686 } 1687 if (isResizable()) { 1688 states.add(AccessibleState.RESIZABLE); 1689 } 1690 return states; 1691 } 1692 1693 } // inner class AccessibleAWTDialog 1694 } 1695