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