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