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