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