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 &amp; 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 }