1 /* 2 * Copyright (c) 1995, 2014, 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 @SuppressWarnings("deprecation") 753 public void addNotify() { 754 synchronized (getTreeLock()) { 755 if (parent != null && parent.getPeer() == null) { 756 parent.addNotify(); 757 } 758 759 if (peer == null) { 760 peer = getToolkit().createDialog(this); 761 } 762 super.addNotify(); 763 } 764 } 765 766 /** 767 * Indicates whether the dialog is modal. 768 * <p> 769 * This method is obsolete and is kept for backwards compatibility only. 770 * Use {@link #getModalityType getModalityType()} instead. 771 * 772 * @return <code>true</code> if this dialog window is modal; 773 * <code>false</code> otherwise 774 * 775 * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE 776 * @see java.awt.Dialog.ModalityType#MODELESS 777 * @see java.awt.Dialog#setModal 778 * @see java.awt.Dialog#getModalityType 779 * @see java.awt.Dialog#setModalityType 780 */ 781 public boolean isModal() { 782 return isModal_NoClientCode(); 783 } 784 final boolean isModal_NoClientCode() { 785 return modalityType != ModalityType.MODELESS; 786 } 787 788 /** 789 * Specifies whether this dialog should be modal. 790 * <p> 791 * This method is obsolete and is kept for backwards compatibility only. 792 * Use {@link #setModalityType setModalityType()} instead. 793 * <p> 794 * Note: changing modality of the visible dialog may have no effect 795 * until it is hidden and then shown again. 796 * 797 * @param modal specifies whether dialog blocks input to other windows 798 * when shown; calling to <code>setModal(true)</code> is equivalent to 799 * <code>setModalityType(Dialog.DEFAULT_MODALITY_TYPE)</code>, and 800 * calling to <code>setModal(false)</code> is equivalent to 801 * <code>setModalityType(Dialog.ModalityType.MODELESS)</code> 802 * 803 * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE 804 * @see java.awt.Dialog.ModalityType#MODELESS 805 * @see java.awt.Dialog#isModal 806 * @see java.awt.Dialog#getModalityType 807 * @see java.awt.Dialog#setModalityType 808 * 809 * @since 1.1 810 */ 811 public void setModal(boolean modal) { 812 this.modal = modal; 813 setModalityType(modal ? DEFAULT_MODALITY_TYPE : ModalityType.MODELESS); 814 } 815 816 /** 817 * Returns the modality type of this dialog. 818 * 819 * @return modality type of this dialog 820 * 821 * @see java.awt.Dialog#setModalityType 822 * 823 * @since 1.6 824 */ 825 public ModalityType getModalityType() { 826 return modalityType; 827 } 828 829 /** 830 * Sets the modality type for this dialog. See {@link 831 * java.awt.Dialog.ModalityType ModalityType} for possible modality types. 832 * <p> 833 * If the given modality type is not supported, <code>MODELESS</code> 834 * is used. You may want to call <code>getModalityType()</code> after calling 835 * this method to ensure that the modality type has been set. 836 * <p> 837 * Note: changing modality of the visible dialog may have no effect 838 * until it is hidden and then shown again. 839 * 840 * @param type specifies whether dialog blocks input to other 841 * windows when shown. <code>null</code> value and unsupported modality 842 * types are equivalent to <code>MODELESS</code> 843 * @exception SecurityException if the calling thread does not have permission 844 * to create modal dialogs with the given <code>modalityType</code> 845 * 846 * @see java.awt.Dialog#getModalityType 847 * @see java.awt.Toolkit#isModalityTypeSupported 848 * 849 * @since 1.6 850 */ 851 public void setModalityType(ModalityType type) { 852 if (type == null) { 853 type = Dialog.ModalityType.MODELESS; 854 } 855 if (!Toolkit.getDefaultToolkit().isModalityTypeSupported(type)) { 856 type = Dialog.ModalityType.MODELESS; 857 } 858 if (modalityType == type) { 859 return; 860 } 861 862 checkModalityPermission(type); 863 864 modalityType = type; 865 modal = (modalityType != ModalityType.MODELESS); 866 } 867 868 /** 869 * Gets the title of the dialog. The title is displayed in the 870 * dialog's border. 871 * @return the title of this dialog window. The title may be 872 * <code>null</code>. 873 * @see java.awt.Dialog#setTitle 874 */ 875 public String getTitle() { 876 return title; 877 } 878 879 /** 880 * Sets the title of the Dialog. 881 * @param title the title displayed in the dialog's border; 882 * a null value results in an empty title 883 * @see #getTitle 884 */ 885 public void setTitle(String title) { 886 String oldTitle = this.title; 887 888 synchronized(this) { 889 this.title = title; 890 DialogPeer peer = (DialogPeer)this.peer; 891 if (peer != null) { 892 peer.setTitle(title); 893 } 894 } 895 firePropertyChange("title", oldTitle, title); 896 } 897 898 /** 899 * @return true if we actually showed, false if we just called toFront() 900 */ 901 @SuppressWarnings("deprecation") 902 private boolean conditionalShow(Component toFocus, AtomicLong time) { 903 boolean retval; 904 905 closeSplashScreen(); 906 907 synchronized (getTreeLock()) { 908 if (peer == null) { 909 addNotify(); 910 } 911 validateUnconditionally(); 912 if (visible) { 913 toFront(); 914 retval = false; 915 } else { 916 visible = retval = true; 917 918 // check if this dialog should be modal blocked BEFORE calling peer.show(), 919 // otherwise, a pair of FOCUS_GAINED and FOCUS_LOST may be mistakenly 920 // generated for the dialog 921 if (!isModal()) { 922 checkShouldBeBlocked(this); 923 } else { 924 modalDialogs.add(this); 925 modalShow(); 926 } 927 928 if (toFocus != null && time != null && isFocusable() && 929 isEnabled() && !isModalBlocked()) { 930 // keep the KeyEvents from being dispatched 931 // until the focus has been transferred 932 time.set(Toolkit.getEventQueue().getMostRecentKeyEventTime()); 933 KeyboardFocusManager.getCurrentKeyboardFocusManager(). 934 enqueueKeyEvents(time.get(), toFocus); 935 } 936 937 // This call is required as the show() method of the Dialog class 938 // does not invoke the super.show(). So wried... :( 939 mixOnShowing(); 940 941 peer.setVisible(true); // now guaranteed never to block 942 if (isModalBlocked()) { 943 modalBlocker.toFront(); 944 } 945 946 setLocationByPlatform(false); 947 for (int i = 0; i < ownedWindowList.size(); i++) { 948 Window child = ownedWindowList.elementAt(i).get(); 949 if ((child != null) && child.showWithParent) { 950 child.show(); 951 child.showWithParent = false; 952 } // endif 953 } // endfor 954 Window.updateChildFocusableWindowState(this); 955 956 createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, 957 this, parent, 958 HierarchyEvent.SHOWING_CHANGED, 959 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); 960 if (componentListener != null || 961 (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0 || 962 Toolkit.enabledOnToolkit(AWTEvent.COMPONENT_EVENT_MASK)) { 963 ComponentEvent e = 964 new ComponentEvent(this, ComponentEvent.COMPONENT_SHOWN); 965 Toolkit.getEventQueue().postEvent(e); 966 } 967 } 968 } 969 970 if (retval && (state & OPENED) == 0) { 971 postWindowEvent(WindowEvent.WINDOW_OPENED); 972 state |= OPENED; 973 } 974 975 return retval; 976 } 977 978 /** 979 * Shows or hides this {@code Dialog} depending on the value of parameter 980 * {@code b}. 981 * @param b if {@code true}, makes the {@code Dialog} visible, 982 * otherwise hides the {@code Dialog}. 983 * If the dialog and/or its owner 984 * are not yet displayable, both are made displayable. The 985 * dialog will be validated prior to being made visible. 986 * If {@code false}, hides the {@code Dialog} and then causes {@code setVisible(true)} 987 * to return if it is currently blocked. 988 * <p> 989 * <b>Notes for modal dialogs</b>. 990 * <ul> 991 * <li>{@code setVisible(true)}: If the dialog is not already 992 * visible, this call will not return until the dialog is 993 * hidden by calling {@code setVisible(false)} or 994 * {@code dispose}. 995 * <li>{@code setVisible(false)}: Hides the dialog and then 996 * returns on {@code setVisible(true)} if it is currently blocked. 997 * <li>It is OK to call this method from the event dispatching 998 * thread because the toolkit ensures that other events are 999 * not blocked while this method is blocked. 1000 * </ul> 1001 * @see java.awt.Window#setVisible 1002 * @see java.awt.Window#dispose 1003 * @see java.awt.Component#isDisplayable 1004 * @see java.awt.Component#validate 1005 * @see java.awt.Dialog#isModal 1006 */ 1007 public void setVisible(boolean b) { 1008 super.setVisible(b); 1009 } 1010 1011 /** 1012 * Makes the {@code Dialog} visible. If the dialog and/or its owner 1013 * are not yet displayable, both are made displayable. The 1014 * dialog will be validated prior to being made visible. 1015 * If the dialog is already visible, this will bring the dialog 1016 * to the front. 1017 * <p> 1018 * If the dialog is modal and is not already visible, this call 1019 * will not return until the dialog is hidden by calling hide or 1020 * dispose. It is permissible to show modal dialogs from the event 1021 * dispatching thread because the toolkit will ensure that another 1022 * event pump runs while the one which invoked this method is blocked. 1023 * @see Component#hide 1024 * @see Component#isDisplayable 1025 * @see Component#validate 1026 * @see #isModal 1027 * @see Window#setVisible(boolean) 1028 * @deprecated As of JDK version 1.5, replaced by 1029 * {@link #setVisible(boolean) setVisible(boolean)}. 1030 */ 1031 @Deprecated 1032 public void show() { 1033 if (!initialized) { 1034 throw new IllegalStateException("The dialog component " + 1035 "has not been initialized properly"); 1036 } 1037 1038 beforeFirstShow = false; 1039 if (!isModal()) { 1040 conditionalShow(null, null); 1041 } else { 1042 AppContext showAppContext = AppContext.getAppContext(); 1043 1044 AtomicLong time = new AtomicLong(); 1045 Component predictedFocusOwner = null; 1046 try { 1047 predictedFocusOwner = getMostRecentFocusOwner(); 1048 if (conditionalShow(predictedFocusOwner, time)) { 1049 modalFilter = ModalEventFilter.createFilterForDialog(this); 1050 // if this dialog is toolkit-modal, the filter should be added 1051 // to all EDTs (for all AppContexts) 1052 if (modalityType == ModalityType.TOOLKIT_MODAL) { 1053 Iterator<AppContext> it = AppContext.getAppContexts().iterator(); 1054 while (it.hasNext()) { 1055 AppContext appContext = it.next(); 1056 if (appContext == showAppContext) { 1057 continue; 1058 } 1059 EventQueue eventQueue = (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY); 1060 // it may occur that EDT for appContext hasn't been started yet, so 1061 // we post an empty invocation event to trigger EDT initialization 1062 eventQueue.postEvent(new InvocationEvent(this, () -> {})); 1063 EventDispatchThread edt = eventQueue.getDispatchThread(); 1064 edt.addEventFilter(modalFilter); 1065 } 1066 } 1067 1068 modalityPushed(); 1069 try { 1070 final EventQueue eventQueue = AccessController.doPrivileged( 1071 (PrivilegedAction<EventQueue>) Toolkit.getDefaultToolkit()::getSystemEventQueue); 1072 secondaryLoop = eventQueue.createSecondaryLoop(() -> true, modalFilter, 0); 1073 if (!secondaryLoop.enter()) { 1074 secondaryLoop = null; 1075 } 1076 } finally { 1077 modalityPopped(); 1078 } 1079 1080 // if this dialog is toolkit-modal, its filter must be removed 1081 // from all EDTs (for all AppContexts) 1082 if (modalityType == ModalityType.TOOLKIT_MODAL) { 1083 Iterator<AppContext> it = AppContext.getAppContexts().iterator(); 1084 while (it.hasNext()) { 1085 AppContext appContext = it.next(); 1086 if (appContext == showAppContext) { 1087 continue; 1088 } 1089 EventQueue eventQueue = (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY); 1090 EventDispatchThread edt = eventQueue.getDispatchThread(); 1091 edt.removeEventFilter(modalFilter); 1092 } 1093 } 1094 } 1095 } finally { 1096 if (predictedFocusOwner != null) { 1097 // Restore normal key event dispatching 1098 KeyboardFocusManager.getCurrentKeyboardFocusManager(). 1099 dequeueKeyEvents(time.get(), predictedFocusOwner); 1100 } 1101 } 1102 } 1103 } 1104 1105 final void modalityPushed() { 1106 Toolkit tk = Toolkit.getDefaultToolkit(); 1107 if (tk instanceof SunToolkit) { 1108 SunToolkit stk = (SunToolkit)tk; 1109 stk.notifyModalityPushed(this); 1110 } 1111 } 1112 1113 final void modalityPopped() { 1114 Toolkit tk = Toolkit.getDefaultToolkit(); 1115 if (tk instanceof SunToolkit) { 1116 SunToolkit stk = (SunToolkit)tk; 1117 stk.notifyModalityPopped(this); 1118 } 1119 } 1120 1121 private void hideAndDisposePreHandler() { 1122 isInHide = true; 1123 synchronized (getTreeLock()) { 1124 if (secondaryLoop != null) { 1125 modalHide(); 1126 // dialog can be shown and then disposed before its 1127 // modal filter is created 1128 if (modalFilter != null) { 1129 modalFilter.disable(); 1130 } 1131 modalDialogs.remove(this); 1132 } 1133 } 1134 } 1135 private void hideAndDisposeHandler() { 1136 if (secondaryLoop != null) { 1137 secondaryLoop.exit(); 1138 secondaryLoop = null; 1139 } 1140 isInHide = false; 1141 } 1142 1143 /** 1144 * Hides the Dialog and then causes {@code show} to return if it is currently 1145 * blocked. 1146 * @see Window#show 1147 * @see Window#dispose 1148 * @see Window#setVisible(boolean) 1149 * @deprecated As of JDK version 1.5, replaced by 1150 * {@link #setVisible(boolean) setVisible(boolean)}. 1151 */ 1152 @Deprecated 1153 public void hide() { 1154 hideAndDisposePreHandler(); 1155 super.hide(); 1156 // fix for 5048370: if hide() is called from super.doDispose(), then 1157 // hideAndDisposeHandler() should not be called here as it will be called 1158 // at the end of doDispose() 1159 if (!isInDispose) { 1160 hideAndDisposeHandler(); 1161 } 1162 } 1163 1164 /** 1165 * Disposes the Dialog and then causes show() to return if it is currently 1166 * blocked. 1167 */ 1168 void doDispose() { 1169 // fix for 5048370: set isInDispose flag to true to prevent calling 1170 // to hideAndDisposeHandler() from hide() 1171 isInDispose = true; 1172 super.doDispose(); 1173 hideAndDisposeHandler(); 1174 isInDispose = false; 1175 } 1176 1177 /** 1178 * {@inheritDoc} 1179 * <p> 1180 * If this dialog is modal and blocks some windows, then all of them are 1181 * also sent to the back to keep them below the blocking dialog. 1182 * 1183 * @see java.awt.Window#toBack 1184 */ 1185 public void toBack() { 1186 super.toBack(); 1187 if (visible) { 1188 synchronized (getTreeLock()) { 1189 for (Window w : blockedWindows) { 1190 w.toBack_NoClientCode(); 1191 } 1192 } 1193 } 1194 } 1195 1196 /** 1197 * Indicates whether this dialog is resizable by the user. 1198 * By default, all dialogs are initially resizable. 1199 * @return <code>true</code> if the user can resize the dialog; 1200 * <code>false</code> otherwise. 1201 * @see java.awt.Dialog#setResizable 1202 */ 1203 public boolean isResizable() { 1204 return resizable; 1205 } 1206 1207 /** 1208 * Sets whether this dialog is resizable by the user. 1209 * @param resizable <code>true</code> if the user can 1210 * resize this dialog; <code>false</code> otherwise. 1211 * @see java.awt.Dialog#isResizable 1212 */ 1213 public void setResizable(boolean resizable) { 1214 boolean testvalid = false; 1215 1216 synchronized (this) { 1217 this.resizable = resizable; 1218 DialogPeer peer = (DialogPeer)this.peer; 1219 if (peer != null) { 1220 peer.setResizable(resizable); 1221 testvalid = true; 1222 } 1223 } 1224 1225 // On some platforms, changing the resizable state affects 1226 // the insets of the Dialog. If we could, we'd call invalidate() 1227 // from the peer, but we need to guarantee that we're not holding 1228 // the Dialog lock when we call invalidate(). 1229 if (testvalid) { 1230 invalidateIfValid(); 1231 } 1232 } 1233 1234 1235 /** 1236 * Disables or enables decorations for this dialog. 1237 * <p> 1238 * This method can only be called while the dialog is not displayable. To 1239 * make this dialog decorated, it must be opaque and have the default shape, 1240 * otherwise the {@code IllegalComponentStateException} will be thrown. 1241 * Refer to {@link Window#setShape}, {@link Window#setOpacity} and {@link 1242 * Window#setBackground} for details 1243 * 1244 * @param undecorated {@code true} if no dialog decorations are to be 1245 * enabled; {@code false} if dialog decorations are to be enabled 1246 * 1247 * @throws IllegalComponentStateException if the dialog is displayable 1248 * @throws IllegalComponentStateException if {@code undecorated} is 1249 * {@code false}, and this dialog does not have the default shape 1250 * @throws IllegalComponentStateException if {@code undecorated} is 1251 * {@code false}, and this dialog opacity is less than {@code 1.0f} 1252 * @throws IllegalComponentStateException if {@code undecorated} is 1253 * {@code false}, and the alpha value of this dialog background 1254 * color is less than {@code 1.0f} 1255 * 1256 * @see #isUndecorated 1257 * @see Component#isDisplayable 1258 * @see Window#getShape 1259 * @see Window#getOpacity 1260 * @see Window#getBackground 1261 * 1262 * @since 1.4 1263 */ 1264 public void setUndecorated(boolean undecorated) { 1265 /* Make sure we don't run in the middle of peer creation.*/ 1266 synchronized (getTreeLock()) { 1267 if (isDisplayable()) { 1268 throw new IllegalComponentStateException("The dialog is displayable."); 1269 } 1270 if (!undecorated) { 1271 if (getOpacity() < 1.0f) { 1272 throw new IllegalComponentStateException("The dialog is not opaque"); 1273 } 1274 if (getShape() != null) { 1275 throw new IllegalComponentStateException("The dialog does not have a default shape"); 1276 } 1277 Color bg = getBackground(); 1278 if ((bg != null) && (bg.getAlpha() < 255)) { 1279 throw new IllegalComponentStateException("The dialog background color is not opaque"); 1280 } 1281 } 1282 this.undecorated = undecorated; 1283 } 1284 } 1285 1286 /** 1287 * Indicates whether this dialog is undecorated. 1288 * By default, all dialogs are initially decorated. 1289 * @return <code>true</code> if dialog is undecorated; 1290 * <code>false</code> otherwise. 1291 * @see java.awt.Dialog#setUndecorated 1292 * @since 1.4 1293 */ 1294 public boolean isUndecorated() { 1295 return undecorated; 1296 } 1297 1298 /** 1299 * {@inheritDoc} 1300 */ 1301 @Override 1302 public void setOpacity(float opacity) { 1303 synchronized (getTreeLock()) { 1304 if ((opacity < 1.0f) && !isUndecorated()) { 1305 throw new IllegalComponentStateException("The dialog is decorated"); 1306 } 1307 super.setOpacity(opacity); 1308 } 1309 } 1310 1311 /** 1312 * {@inheritDoc} 1313 */ 1314 @Override 1315 public void setShape(Shape shape) { 1316 synchronized (getTreeLock()) { 1317 if ((shape != null) && !isUndecorated()) { 1318 throw new IllegalComponentStateException("The dialog is decorated"); 1319 } 1320 super.setShape(shape); 1321 } 1322 } 1323 1324 /** 1325 * {@inheritDoc} 1326 */ 1327 @Override 1328 public void setBackground(Color bgColor) { 1329 synchronized (getTreeLock()) { 1330 if ((bgColor != null) && (bgColor.getAlpha() < 255) && !isUndecorated()) { 1331 throw new IllegalComponentStateException("The dialog is decorated"); 1332 } 1333 super.setBackground(bgColor); 1334 } 1335 } 1336 1337 /** 1338 * Returns a string representing the state of this dialog. This 1339 * method is intended to be used only for debugging purposes, and the 1340 * content and format of the returned string may vary between 1341 * implementations. The returned string may be empty but may not be 1342 * <code>null</code>. 1343 * 1344 * @return the parameter string of this dialog window. 1345 */ 1346 protected String paramString() { 1347 String str = super.paramString() + "," + modalityType; 1348 if (title != null) { 1349 str += ",title=" + title; 1350 } 1351 return str; 1352 } 1353 1354 /** 1355 * Initialize JNI field and method IDs 1356 */ 1357 private static native void initIDs(); 1358 1359 /* 1360 * --- Modality support --- 1361 * 1362 */ 1363 1364 /* 1365 * This method is called only for modal dialogs. 1366 * 1367 * Goes through the list of all visible top-level windows and 1368 * divide them into three distinct groups: blockers of this dialog, 1369 * blocked by this dialog and all others. Then blocks this dialog 1370 * by first met dialog from the first group (if any) and blocks all 1371 * the windows from the second group. 1372 */ 1373 void modalShow() { 1374 // find all the dialogs that block this one 1375 IdentityArrayList<Dialog> blockers = new IdentityArrayList<Dialog>(); 1376 for (Dialog d : modalDialogs) { 1377 if (d.shouldBlock(this)) { 1378 Window w = d; 1379 while ((w != null) && (w != this)) { 1380 w = w.getOwner_NoClientCode(); 1381 } 1382 if ((w == this) || !shouldBlock(d) || (modalityType.compareTo(d.getModalityType()) < 0)) { 1383 blockers.add(d); 1384 } 1385 } 1386 } 1387 1388 // add all blockers' blockers to blockers :) 1389 for (int i = 0; i < blockers.size(); i++) { 1390 Dialog blocker = blockers.get(i); 1391 if (blocker.isModalBlocked()) { 1392 Dialog blockerBlocker = blocker.getModalBlocker(); 1393 if (!blockers.contains(blockerBlocker)) { 1394 blockers.add(i + 1, blockerBlocker); 1395 } 1396 } 1397 } 1398 1399 if (blockers.size() > 0) { 1400 blockers.get(0).blockWindow(this); 1401 } 1402 1403 // find all windows from blockers' hierarchies 1404 IdentityArrayList<Window> blockersHierarchies = new IdentityArrayList<Window>(blockers); 1405 int k = 0; 1406 while (k < blockersHierarchies.size()) { 1407 Window w = blockersHierarchies.get(k); 1408 Window[] ownedWindows = w.getOwnedWindows_NoClientCode(); 1409 for (Window win : ownedWindows) { 1410 blockersHierarchies.add(win); 1411 } 1412 k++; 1413 } 1414 1415 java.util.List<Window> toBlock = new IdentityLinkedList<Window>(); 1416 // block all windows from scope of blocking except from blockers' hierarchies 1417 IdentityArrayList<Window> unblockedWindows = Window.getAllUnblockedWindows(); 1418 for (Window w : unblockedWindows) { 1419 if (shouldBlock(w) && !blockersHierarchies.contains(w)) { 1420 if ((w instanceof Dialog) && ((Dialog)w).isModal_NoClientCode()) { 1421 Dialog wd = (Dialog)w; 1422 if (wd.shouldBlock(this) && (modalDialogs.indexOf(wd) > modalDialogs.indexOf(this))) { 1423 continue; 1424 } 1425 } 1426 toBlock.add(w); 1427 } 1428 } 1429 blockWindows(toBlock); 1430 1431 if (!isModalBlocked()) { 1432 updateChildrenBlocking(); 1433 } 1434 } 1435 1436 /* 1437 * This method is called only for modal dialogs. 1438 * 1439 * Unblocks all the windows blocked by this modal dialog. After 1440 * each of them has been unblocked, it is checked to be blocked by 1441 * any other modal dialogs. 1442 */ 1443 void modalHide() { 1444 // we should unblock all the windows first... 1445 IdentityArrayList<Window> save = new IdentityArrayList<Window>(); 1446 int blockedWindowsCount = blockedWindows.size(); 1447 for (int i = 0; i < blockedWindowsCount; i++) { 1448 Window w = blockedWindows.get(0); 1449 save.add(w); 1450 unblockWindow(w); // also removes w from blockedWindows 1451 } 1452 // ... and only after that check if they should be blocked 1453 // by another dialogs 1454 for (int i = 0; i < blockedWindowsCount; i++) { 1455 Window w = save.get(i); 1456 if ((w instanceof Dialog) && ((Dialog)w).isModal_NoClientCode()) { 1457 Dialog d = (Dialog)w; 1458 d.modalShow(); 1459 } else { 1460 checkShouldBeBlocked(w); 1461 } 1462 } 1463 } 1464 1465 /* 1466 * Returns whether the given top-level window should be blocked by 1467 * this dialog. Note, that the given window can be also a modal dialog 1468 * and it should block this dialog, but this method do not take such 1469 * situations into consideration (such checks are performed in the 1470 * modalShow() and modalHide() methods). 1471 * 1472 * This method should be called on the getTreeLock() lock. 1473 */ 1474 boolean shouldBlock(Window w) { 1475 if (!isVisible_NoClientCode() || 1476 (!w.isVisible_NoClientCode() && !w.isInShow) || 1477 isInHide || 1478 (w == this) || 1479 !isModal_NoClientCode()) 1480 { 1481 return false; 1482 } 1483 if ((w instanceof Dialog) && ((Dialog)w).isInHide) { 1484 return false; 1485 } 1486 // check if w is from children hierarchy 1487 // fix for 6271546: we should also take into consideration child hierarchies 1488 // of this dialog's blockers 1489 Window blockerToCheck = this; 1490 while (blockerToCheck != null) { 1491 Component c = w; 1492 while ((c != null) && (c != blockerToCheck)) { 1493 c = c.getParent_NoClientCode(); 1494 } 1495 if (c == blockerToCheck) { 1496 return false; 1497 } 1498 blockerToCheck = blockerToCheck.getModalBlocker(); 1499 } 1500 switch (modalityType) { 1501 case MODELESS: 1502 return false; 1503 case DOCUMENT_MODAL: 1504 if (w.isModalExcluded(ModalExclusionType.APPLICATION_EXCLUDE)) { 1505 // application- and toolkit-excluded windows are not blocked by 1506 // document-modal dialogs from outside their children hierarchy 1507 Component c = this; 1508 while ((c != null) && (c != w)) { 1509 c = c.getParent_NoClientCode(); 1510 } 1511 return c == w; 1512 } else { 1513 return getDocumentRoot() == w.getDocumentRoot(); 1514 } 1515 case APPLICATION_MODAL: 1516 return !w.isModalExcluded(ModalExclusionType.APPLICATION_EXCLUDE) && 1517 (appContext == w.appContext); 1518 case TOOLKIT_MODAL: 1519 return !w.isModalExcluded(ModalExclusionType.TOOLKIT_EXCLUDE); 1520 } 1521 1522 return false; 1523 } 1524 1525 /* 1526 * Adds the given top-level window to the list of blocked 1527 * windows for this dialog and marks it as modal blocked. 1528 * If the window is already blocked by some modal dialog, 1529 * does nothing. 1530 */ 1531 void blockWindow(Window w) { 1532 if (!w.isModalBlocked()) { 1533 w.setModalBlocked(this, true, true); 1534 blockedWindows.add(w); 1535 } 1536 } 1537 1538 void blockWindows(java.util.List<Window> toBlock) { 1539 DialogPeer dpeer = (DialogPeer)peer; 1540 if (dpeer == null) { 1541 return; 1542 } 1543 Iterator<Window> it = toBlock.iterator(); 1544 while (it.hasNext()) { 1545 Window w = it.next(); 1546 if (!w.isModalBlocked()) { 1547 w.setModalBlocked(this, true, false); 1548 } else { 1549 it.remove(); 1550 } 1551 } 1552 dpeer.blockWindows(toBlock); 1553 blockedWindows.addAll(toBlock); 1554 } 1555 1556 /* 1557 * Removes the given top-level window from the list of blocked 1558 * windows for this dialog and marks it as unblocked. If the 1559 * window is not modal blocked, does nothing. 1560 */ 1561 void unblockWindow(Window w) { 1562 if (w.isModalBlocked() && blockedWindows.contains(w)) { 1563 blockedWindows.remove(w); 1564 w.setModalBlocked(this, false, true); 1565 } 1566 } 1567 1568 /* 1569 * Checks if any other modal dialog D blocks the given window. 1570 * If such D exists, mark the window as blocked by D. 1571 */ 1572 static void checkShouldBeBlocked(Window w) { 1573 synchronized (w.getTreeLock()) { 1574 for (int i = 0; i < modalDialogs.size(); i++) { 1575 Dialog modalDialog = modalDialogs.get(i); 1576 if (modalDialog.shouldBlock(w)) { 1577 modalDialog.blockWindow(w); 1578 break; 1579 } 1580 } 1581 } 1582 } 1583 1584 private void checkModalityPermission(ModalityType mt) { 1585 if (mt == ModalityType.TOOLKIT_MODAL) { 1586 SecurityManager sm = System.getSecurityManager(); 1587 if (sm != null) { 1588 sm.checkPermission(AWTPermissions.TOOLKIT_MODALITY_PERMISSION); 1589 } 1590 } 1591 } 1592 1593 private void readObject(ObjectInputStream s) 1594 throws ClassNotFoundException, IOException, HeadlessException 1595 { 1596 GraphicsEnvironment.checkHeadless(); 1597 1598 java.io.ObjectInputStream.GetField fields = 1599 s.readFields(); 1600 1601 ModalityType localModalityType = (ModalityType)fields.get("modalityType", null); 1602 1603 try { 1604 checkModalityPermission(localModalityType); 1605 } catch (AccessControlException ace) { 1606 localModalityType = DEFAULT_MODALITY_TYPE; 1607 } 1608 1609 // in 1.5 or earlier modalityType was absent, so use "modal" instead 1610 if (localModalityType == null) { 1611 this.modal = fields.get("modal", false); 1612 setModal(modal); 1613 } else { 1614 this.modalityType = localModalityType; 1615 } 1616 1617 this.resizable = fields.get("resizable", true); 1618 this.undecorated = fields.get("undecorated", false); 1619 this.title = (String)fields.get("title", ""); 1620 1621 blockedWindows = new IdentityArrayList<>(); 1622 1623 SunToolkit.checkAndSetPolicy(this); 1624 1625 initialized = true; 1626 1627 } 1628 1629 /* 1630 * --- Accessibility Support --- 1631 * 1632 */ 1633 1634 /** 1635 * Gets the AccessibleContext associated with this Dialog. 1636 * For dialogs, the AccessibleContext takes the form of an 1637 * AccessibleAWTDialog. 1638 * A new AccessibleAWTDialog instance is created if necessary. 1639 * 1640 * @return an AccessibleAWTDialog that serves as the 1641 * AccessibleContext of this Dialog 1642 * @since 1.3 1643 */ 1644 public AccessibleContext getAccessibleContext() { 1645 if (accessibleContext == null) { 1646 accessibleContext = new AccessibleAWTDialog(); 1647 } 1648 return accessibleContext; 1649 } 1650 1651 /** 1652 * This class implements accessibility support for the 1653 * <code>Dialog</code> class. It provides an implementation of the 1654 * Java Accessibility API appropriate to dialog user-interface elements. 1655 * @since 1.3 1656 */ 1657 protected class AccessibleAWTDialog extends AccessibleAWTWindow 1658 { 1659 /* 1660 * JDK 1.3 serialVersionUID 1661 */ 1662 private static final long serialVersionUID = 4837230331833941201L; 1663 1664 /** 1665 * Get the role of this object. 1666 * 1667 * @return an instance of AccessibleRole describing the role of the 1668 * object 1669 * @see AccessibleRole 1670 */ 1671 public AccessibleRole getAccessibleRole() { 1672 return AccessibleRole.DIALOG; 1673 } 1674 1675 /** 1676 * Get the state of this object. 1677 * 1678 * @return an instance of AccessibleStateSet containing the current 1679 * state set of the object 1680 * @see AccessibleState 1681 */ 1682 public AccessibleStateSet getAccessibleStateSet() { 1683 AccessibleStateSet states = super.getAccessibleStateSet(); 1684 if (getFocusOwner() != null) { 1685 states.add(AccessibleState.ACTIVE); 1686 } 1687 if (isModal()) { 1688 states.add(AccessibleState.MODAL); 1689 } 1690 if (isResizable()) { 1691 states.add(AccessibleState.RESIZABLE); 1692 } 1693 return states; 1694 } 1695 1696 } // inner class AccessibleAWTDialog 1697 }