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
26  * @bug 8155740
27  * @key headful
28  * @summary See <rdar://problem/3429130>: Events: actionPerformed() method not
29  *              called when it is button is clicked (system load related)
30  * @summary com.apple.junit.java.awt.Frame
31  * @library ../../../regtesthelpers
32  * @build VisibilityValidator
33  * @build Util
34  * @build Waypoint
35  * @run main NestedModelessDialogTest -Xlog:exception
36  */
37 
38 /////////////////////////////////////////////////////////////////////////////
39 //  NestedModelessDialogTest.java
40 // The test launches a parent frame. From this parent frame it launches a modal
41 // dialog. From the modal dialog it launches a modeless dialog with a text
42 // field in it and tries to write into the text field. The test succeeds if you
43 // are successfully able to write into this Nested Modeless Dialog
44 /////////////////////////////////////////////////////////////////////////////
45 // classes necessary for this test
46 import java.awt.*;
47 import java.awt.event.*;
48 import java.util.Enumeration;
49 
50 import test.java.awt.regtesthelpers.Util;
51 import test.java.awt.regtesthelpers.VisibilityValidator;
52 import test.java.awt.regtesthelpers.Waypoint;
53 
54 public class NestedModelessDialogTest {
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      * Get called by test harness
69      *
70      * @throws Exception
71      */
testModelessDialogs()72     public void testModelessDialogs() throws Exception {
73         Frame frame = null;
74         String result = "";
75         Robot robot = getRobot();
76 
77         event_checkpoint[0] = new Waypoint(); // "-Launch 1-"
78         event_checkpoint[1] = new Waypoint(); // "-Launch 2-"
79 
80         // launch first frame with fistButton
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();
89         win_checkpoint[0].requireVisible();
90         Util.clickOnComp(robot_button[1], robot);
91 
92         // Again, the Dialog must be created and onscreen before we proceed.
93         //   The event_checkpoint waits for the Dialog to be created.
94         //   The win_checkpoint waits for the Dialog to be visible.
95         event_checkpoint[1].requireClear();
96         win_checkpoint[1].requireVisible();
97         Util.clickOnComp(robot_text, robot);
98 
99         // I'm really not sure whether the click is needed for focus
100         // but since it's asynchronous, as is the actually gaining of focus
101         // we might as well do our best
102         try {
103             EventQueue.invokeAndWait(new Runnable() {
104                 public void run() {
105                 }
106             });
107         } catch (Exception e) {
108         }
109 
110         robot.keyPress(KeyEvent.VK_SHIFT);
111 
112         robot.keyPress(KeyEvent.VK_H);
113         robot.waitForIdle();
114         robot.keyRelease(KeyEvent.VK_H);
115 
116         robot.keyRelease(KeyEvent.VK_SHIFT);
117 
118         robot.keyPress(KeyEvent.VK_E);
119         robot.waitForIdle();
120         robot.keyRelease(KeyEvent.VK_E);
121 
122         robot.keyPress(KeyEvent.VK_L);
123         robot.waitForIdle();
124         robot.keyRelease(KeyEvent.VK_L);
125 
126         robot.keyPress(KeyEvent.VK_L);
127         robot.waitForIdle();
128         robot.keyRelease(KeyEvent.VK_L);
129 
130         robot.keyPress(KeyEvent.VK_O);
131         robot.waitForIdle();
132         robot.keyRelease(KeyEvent.VK_O);
133 
134         //
135         // NOTE THAT WE MAY HAVE MORE SYNCHRONIZATION WORK TO DO HERE.
136         // CURRENTLY THERE IS NO GUARANTEE THAT THE KEYEVENT THAT THAT
137         // TYPES THE 'O' HAS BEEN PROCESSED BEFORE WE GET THE RESULT
138         //
139         // This is a (lame) attempt at waiting for the last typeKey events to
140         // propagate. It's not quite right because robot uses
141         // CGRemoteOperations, which are asynchronous. But that's why I put in
142         // the Thread.sleep
143         try {
144             EventQueue.invokeAndWait(new Runnable() {
145                 public void run() {
146                 }
147             });
148         } catch (Exception e) {
149         }
150 
151         // Need to call this before the dialog that robot_text is in is disposed
152         result = robot_text.getText();
153 
154         Thread.sleep(50); // Thread.sleep adds stability
155         // Click Close box of modeless dialog with textField
156         Util.clickOnComp(txtDiag, robot);
157 
158         Thread.sleep(50); // Thread.sleep adds stability
159         // Click Close box of intermediate modal dialog
160         Util.clickOnComp(interDiag, robot);
161 
162         Thread.sleep(50); // Thread.sleep adds stability
163         // Click Close box of intermediate modal dialog
164         Util.clickOnComp(frame, robot);
165 
166         String expected = "Hello";
167     }
168 
getRobot()169     private static Robot getRobot() {
170         if (_robot == null) {
171             try {
172                 _robot = new Robot();
173             } catch (AWTException e) {
174                 throw new RuntimeException("Robot creation failed");
175             }
176         }
177         return _robot;
178     }
179 
180     //////////////////// Start Frame ///////////////////
181     /**
182      * Launches the first frame with a button in it
183      */
184     class StartFrame extends Frame {
185 
186         /**
187          * Constructs a new instance.
188          */
StartFrame()189         public StartFrame() {
190             super("First Frame");
191             setLayout(new GridBagLayout());
192             setLocation(375, 200);
193             setSize(271, 161);
194             Button but = new Button("Make Intermediate");
195             but.addActionListener(new java.awt.event.ActionListener() {
196                 public void actionPerformed(ActionEvent e) {
197                     interDiag = new IntermediateDialog(StartFrame.this);
198                     win_checkpoint[0] = new VisibilityValidator(interDiag);
199                     interDiag.setSize(300, 200);
200 
201                     // may need listener to watch this move.
202                     interDiag.setLocation(getLocationOnScreen());
203                     interDiag.pack();
204                     event_checkpoint[0].clear();
205                     interDiag.setVisible(true);
206                 }
207             });
208             Panel pan = new Panel();
209             pan.add(but);
210             add(pan);
211             robot_button[0] = but;
212             addWindowListener(new WindowAdapter() {
213                 public void windowClosing(WindowEvent e) {
214                     setVisible(false);
215                     dispose();
216                 }
217             });
218         }
219     }
220 
221     ///////////////////////////// VARIOUS DIALOGS //////////////////////////
222     /* A Dialog that launches a sub-dialog */
223     class IntermediateDialog extends Dialog {
224 
225         Dialog m_parent;
226 
IntermediateDialog(Frame parent)227         public IntermediateDialog(Frame parent) {
228             super(parent, "Intermediate Modal", true /*Modal*/);
229             m_parent = this;
230             Button but = new Button("Make Text");
231             but.addActionListener(new java.awt.event.ActionListener() {
232                 public void actionPerformed(ActionEvent e) {
233                     txtDiag = new TextDialog(m_parent);
234                     win_checkpoint[1] = new VisibilityValidator(txtDiag);
235                     txtDiag.setSize(300, 100);
236                     event_checkpoint[1].clear();
237                     txtDiag.setVisible(true);
238                 }
239             });
240             Panel pan = new Panel();
241             pan.add(but);
242             add(pan);
243             pack();
244             addWindowListener(new WindowAdapter() {
245                 public void windowClosing(WindowEvent e) {
246                     setVisible(false);
247                     dispose();
248                 }
249             });
250 
251             // The robot needs to know about us, so set global
252             robot_button[1] = but;
253         }
254     }
255 
256     /* A Dialog that just holds a text field */
257     class TextDialog extends Dialog {
258 
TextDialog(Dialog parent)259         public TextDialog(Dialog parent) {
260             super(parent, "Modeless Dialog", false /*Modeless*/);
261             TextField txt = new TextField("", 10);
262             Panel pan = new Panel();
263             pan.add(txt);
264             add(pan);
265             pack();
266             addWindowListener(new WindowAdapter() {
267                 public void windowClosing(WindowEvent e) {
268                     setVisible(false);
269                     dispose();
270                 }
271             });
272 
273             // The robot needs to know about us, so set global
274             robot_text = txt;
275         }
276     }
277 
main(String[] args)278     public static void main(String[] args) throws RuntimeException {
279         try {
280             new NestedModelessDialogTest().testModelessDialogs();
281         } catch (Exception e) {
282             throw new RuntimeException("NestedModelessDialogTest object "
283                     + "creation failed");
284         }
285     }
286 }
287