1 /*
   2  * Copyright (c) 2011, 2017, 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.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * @test 8155740
  26  * @key headful
  27  * @summary See <rdar://problem/3429130>: Events: actionPerformed() method not
  28  *          called when it is button is clicked (system load related)
  29  * @summary com.apple.junit.java.awt.Frame
  30  * @library ../../../regtesthelpers
  31  * @build VisibilityValidator
  32  * @build Util
  33  * @build Waypoint
  34  * @run main NestedModalDialogTest
  35  */
  36 
  37 //////////////////////////////////////////////////////////////////////////////
  38 //  NestedModalDialogTest.java
  39 // The test launches a parent frame. From this parent frame it launches a modal
  40 // dialog. From the modal dialog it launches a second modal dialog with a text
  41 // field in it and tries to write into the text field. The test succeeds if you
  42 // are successfully able to write into this second Nested Modal Dialog
  43 //////////////////////////////////////////////////////////////////////////////
  44 // classes necessary for this test
  45 
  46 import java.awt.*;
  47 import java.awt.event.*;
  48 import java.util.Enumeration;
  49 
  50 import test.java.awt.regtesthelpers.Waypoint;
  51 import test.java.awt.regtesthelpers.VisibilityValidator;
  52 import test.java.awt.regtesthelpers.Util;
  53 
  54 public class NestedModalDialogTest {
  55 
  56     Waypoint[] event_checkpoint = new Waypoint[3];
  57     VisibilityValidator[] win_checkpoint = new VisibilityValidator[2];
  58 
  59     IntermediateDialog interDiag;
  60     TextDialog txtDiag;
  61 
  62     // Global variables so the robot thread can locate things.
  63     Button[] robot_button = new Button[2];
  64     TextField robot_text = null;
  65     static Robot _robot = null;
  66 
  67     /*
  68      * @throws InterruptedException
  69      * @throws WaypointException
  70      */
  71     public void testModalDialogs() throws Exception {
  72         Frame frame = null;
  73         String result = "";
  74         Robot robot = getRobot();
  75 
  76         event_checkpoint[0] = new Waypoint(); // "-Launch 1-"
  77         event_checkpoint[1] = new Waypoint(); // "-Launch 2-"
  78 
  79         // Thread.currentThread().setName("NestedModalDialogTest Thread");
  80         // launch first frame with firstButton
  81         frame = new StartFrame();
  82         VisibilityValidator.setVisibleAndConfirm(frame);
  83         Util.clickOnComp(robot_button[0], robot);
  84 
  85         // Dialog must be created and onscreen before we proceed.
  86         //   The event_checkpoint waits for the Dialog to be created.
  87         //   The win_checkpoint waits for the Dialog to be visible.
  88         event_checkpoint[0].requireClear("TestFrame actionPerformed() never "
  89                 + "called, see <rdar://problem/3429130>");
  90         win_checkpoint[0].requireVisible();
  91         Util.clickOnComp(robot_button[1], robot);
  92 
  93         // Again, the Dialog must be created and onscreen before we proceed.
  94         //   The event_checkpoint waits for the Dialog to be created.
  95         //   The win_checkpoint waits for the Dialog to be visible.
  96         event_checkpoint[1].requireClear("IntermediateDialog actionPerformed() "
  97                 + "never called, see <rdar://problem/3429130>");
  98         win_checkpoint[1].requireVisible();
  99         Util.clickOnComp(robot_text, robot);
 100 
 101         // I'm really not sure whether the click is needed for focus
 102         // but since it's asynchronous, as is the actually gaining of focus
 103         // we might as well do our best
 104         try {
 105             EventQueue.invokeAndWait(new Runnable() {
 106                 public void run() {
 107                 }
 108             });
 109         } catch (Exception e) {
 110         }
 111 
 112         robot.keyPress(KeyEvent.VK_SHIFT);
 113 
 114         robot.keyPress(KeyEvent.VK_H);
 115         robot.waitForIdle();
 116         robot.keyRelease(KeyEvent.VK_H);
 117 
 118         robot.keyRelease(KeyEvent.VK_SHIFT);
 119 
 120         robot.keyPress(KeyEvent.VK_E);
 121         robot.waitForIdle();
 122         robot.keyRelease(KeyEvent.VK_E);
 123 
 124         robot.keyPress(KeyEvent.VK_L);
 125         robot.waitForIdle();
 126         robot.keyRelease(KeyEvent.VK_L);
 127 
 128         robot.keyPress(KeyEvent.VK_L);
 129         robot.waitForIdle();
 130         robot.keyRelease(KeyEvent.VK_L);
 131 
 132         robot.keyPress(KeyEvent.VK_O);
 133         robot.waitForIdle();
 134         robot.keyRelease(KeyEvent.VK_O);
 135 
 136         //
 137         // NOTE THAT WE MAY HAVE MORE SYNCHRONIZATION WORK TO DO HERE.
 138         // CURRENTLY THERE IS NO GUARANTEE THAT THE KEYEVENT THAT THAT
 139         // TYPES THE 'O' HAS BEEN PROCESSED BEFORE WE GET THE RESULT
 140         //
 141         // This is a (lame) attempt at waiting for the last typeKey events to
 142         // propagate. It's not quite right because robot uses
 143         // CGRemoteOperations, which are asynchronous. But that's why I put in
 144         // the pause
 145         try {
 146             EventQueue.invokeAndWait(new Runnable() {
 147                 public void run() {
 148                 }
 149             });
 150         } catch (Exception e) {
 151         }
 152 
 153         // Need to call this before the dialog that robot_text is in is disposed
 154         result = robot_text.getText();
 155 
 156         Thread.sleep(50); // shouldn't need this, but pause adds stability
 157         // Click Close box of modal dialog with textField
 158         Util.clickOnComp(txtDiag, robot);
 159 
 160         Thread.sleep(50); // shouldn't need this, but pause adds stability
 161         // Click Close box of intermediate modal dialog
 162         Util.clickOnComp(interDiag, robot);
 163 
 164         Thread.sleep(50); // shouldn't need this, but pause adds stability
 165         // Click Close box of intermediate modal dialog
 166         Util.clickOnComp(frame, robot);
 167 
 168         String expected = "Hello";
 169     }
 170 
 171     private static Robot getRobot() {
 172         if (_robot == null) {
 173             try {
 174                 _robot = new Robot();
 175             } catch (AWTException e) {
 176                 throw new RuntimeException("Robot creation failed");
 177             }
 178         }
 179         return _robot;
 180     }
 181 
 182     //////////////////// Start Frame ///////////////////
 183     /**
 184      * Launches the first frame with a button in it
 185      */
 186     class StartFrame extends Frame {
 187 
 188         /**
 189          * Constructs a new instance.
 190          */
 191         public StartFrame() {
 192             super("First Frame");
 193             setLayout(new GridBagLayout());
 194             setLocation(375, 200);
 195             setSize(271, 161);
 196             Button but = new Button("Make Intermediate");
 197             but.addActionListener(new java.awt.event.ActionListener() {
 198                 public void actionPerformed(ActionEvent e) {
 199                     interDiag = new IntermediateDialog(StartFrame.this);
 200                     win_checkpoint[0] = new VisibilityValidator(interDiag);
 201                     interDiag.setSize(300, 200);
 202 
 203                     // may need listener to watch this move.
 204                     interDiag.setLocation(getLocationOnScreen());
 205                     interDiag.pack();
 206                     event_checkpoint[0].clear();
 207                     interDiag.setVisible(true);
 208                 }
 209             });
 210             Panel pan = new Panel();
 211             pan.add(but);
 212             add(pan);
 213             robot_button[0] = but;
 214             addWindowListener(new WindowAdapter() {
 215                 public void windowClosing(WindowEvent e) {
 216                     setVisible(false);
 217                     dispose();
 218                 }
 219             });
 220         }
 221     }
 222 
 223     ///////////////////////////// MODAL DIALOGS /////////////////////////////
 224     /* A Dialog that launches a sub-dialog */
 225     class IntermediateDialog extends Dialog {
 226 
 227         Dialog m_parent;
 228 
 229         public IntermediateDialog(Frame parent) {
 230             super(parent, "Intermediate Modal", true /*Modal*/);
 231             m_parent = this;
 232             Button but = new Button("Make Text");
 233             but.addActionListener(new java.awt.event.ActionListener() {
 234                 public void actionPerformed(ActionEvent e) {
 235                     txtDiag = new TextDialog(m_parent);
 236                     win_checkpoint[1] = new VisibilityValidator(txtDiag);
 237                     txtDiag.setSize(300, 100);
 238                     event_checkpoint[1].clear();
 239                     txtDiag.setVisible(true);
 240                 }
 241             });
 242             Panel pan = new Panel();
 243             pan.add(but);
 244             add(pan);
 245             pack();
 246             addWindowListener(new WindowAdapter() {
 247                 public void windowClosing(WindowEvent e) {
 248                     setVisible(false);
 249                     dispose();
 250                 }
 251             });
 252 
 253             // The robot needs to know about us, so set global
 254             robot_button[1] = but;
 255         }
 256     }
 257 
 258     /* A Dialog that just holds a text field */
 259     class TextDialog extends Dialog {
 260 
 261         public TextDialog(Dialog parent) {
 262             super(parent, "Modal Dialog", true /*Modal*/);
 263             TextField txt = new TextField("", 10);
 264             Panel pan = new Panel();
 265             pan.add(txt);
 266             add(pan);
 267             pack();
 268             addWindowListener(new WindowAdapter() {
 269                 public void windowClosing(WindowEvent e) {
 270                     setVisible(false);
 271                     dispose();
 272                 }
 273             });
 274 
 275             // The robot needs to know about us, so set global
 276             robot_text = txt;
 277         }
 278     }
 279 
 280     public static void main(String[] args) throws RuntimeException, Exception {
 281         try {
 282             new NestedModalDialogTest().testModalDialogs();
 283         } catch (Exception e) {
 284             throw new RuntimeException("NestedModalDialogTest object creation "
 285                     + "failed");
 286         }
 287     }
 288 }