1 /*
2  * Copyright (c) 2007, 2018, 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   @key headful
27   @bug 4811096 8173409
28   @summary Tests whether opaque and non-opaque components mix correctly
29   @author anthony.petrov@...: area=awt.mixing
30   @library ../regtesthelpers
31   @build Util
32   @run main OpaqueTest
33 */
34 
35 
36 /**
37  * OpaqueTest.java
38  *
39  * summary:  OpaqueTest
40  */
41 
42 import java.awt.*;
43 import java.awt.event.*;
44 import javax.swing.*;
45 import test.java.awt.regtesthelpers.Util;
46 
47 
48 
49 public class OpaqueTest
50 {
51 
52     //*** test-writer defined static variables go here ***
53 
54     static String testSeq = new String("");
55     final static String checkSeq = new String("010000101");
56 
init()57     private static void init()
58     {
59         // Create components
60         final Frame f = new Frame("Button-JButton mix test");
61         final Panel p = new Panel();
62         final Button heavy = new Button("  Heavyweight Button  ");
63         final JButton light = new JButton("  LW Button  ");
64 
65         // Actions for the buttons add appropriate number to the test sequence
66         heavy.addActionListener(new java.awt.event.ActionListener()
67                 {
68                     public void actionPerformed(java.awt.event.ActionEvent e) {
69                         p.setComponentZOrder(light, 0);
70                         f.validate();
71                         testSeq = testSeq + "0";
72                     }
73                 }
74                 );
75 
76         light.addActionListener(new java.awt.event.ActionListener()
77                 {
78                     public void actionPerformed(java.awt.event.ActionEvent e) {
79                         p.setComponentZOrder(heavy, 0);
80                         f.validate();
81                         testSeq = testSeq + "1";
82                     }
83                 }
84                 );
85 
86         // Overlap the buttons
87         heavy.setBounds(30, 30, 200, 200);
88         light.setBounds(10, 10, 50, 50);
89 
90         // Put the components into the frame
91         p.setLayout(null);
92         p.add(heavy);
93         p.add(light);
94         f.add(p);
95         f.setBounds(50, 50, 400, 400);
96         f.show();
97 
98 
99         Robot robot = Util.createRobot();
100         robot.setAutoDelay(20);
101 
102         Util.waitForIdle(robot);
103 
104         // Move the mouse pointer to the position where both
105         //    buttons overlap
106         Point heavyLoc = heavy.getLocationOnScreen();
107         robot.mouseMove(heavyLoc.x + 5, heavyLoc.y + 5);
108 
109         // Now perform the click at this point for 9 times
110         // In the middle of the process toggle the opaque
111         // flag value.
112         for (int i = 0; i < 9; ++i) {
113             if (i == 3) {
114                 light.setMixingCutoutShape(new Rectangle());
115             }
116             if (i == 6) {
117                 light.setMixingCutoutShape(null);
118             }
119 
120             robot.mousePress(InputEvent.BUTTON1_MASK);
121             robot.mouseRelease(InputEvent.BUTTON1_MASK);
122             Util.waitForIdle(robot);
123         }
124 
125         Util.waitForIdle(robot);
126 
127         // If the buttons are correctly mixed, the test sequence
128         // is equal to the check sequence.
129         if (testSeq.equals(checkSeq)) {
130             OpaqueTest.pass();
131         } else {
132             OpaqueTest.fail("The components changed their visible Z-order in a wrong sequence: '" + testSeq + "' instead of '" + checkSeq + "'");
133         }
134     }//End  init()
135 
136 
137 
138     /*****************************************************
139      * Standard Test Machinery Section
140      * DO NOT modify anything in this section -- it's a
141      * standard chunk of code which has all of the
142      * synchronisation necessary for the test harness.
143      * By keeping it the same in all tests, it is easier
144      * to read and understand someone else's test, as
145      * well as insuring that all tests behave correctly
146      * with the test harness.
147      * There is a section following this for test-
148      * classes
149      ******************************************************/
150     private static boolean theTestPassed = false;
151     private static boolean testGeneratedInterrupt = false;
152     private static String failureMessage = "";
153 
154     private static Thread mainThread = null;
155 
156     private static int sleepTime = 300000;
157 
158     // Not sure about what happens if multiple of this test are
159     //  instantiated in the same VM.  Being static (and using
160     //  static vars), it aint gonna work.  Not worrying about
161     //  it for now.
main( String args[] )162     public static void main( String args[] ) throws InterruptedException
163     {
164         mainThread = Thread.currentThread();
165         try
166         {
167             init();
168         }
169         catch( TestPassedException e )
170         {
171             //The test passed, so just return from main and harness will
172             // interepret this return as a pass
173             return;
174         }
175         //At this point, neither test pass nor test fail has been
176         // called -- either would have thrown an exception and ended the
177         // test, so we know we have multiple threads.
178 
179         //Test involves other threads, so sleep and wait for them to
180         // called pass() or fail()
181         try
182         {
183             Thread.sleep( sleepTime );
184             //Timed out, so fail the test
185             throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
186         }
187         catch (InterruptedException e)
188         {
189             //The test harness may have interrupted the test.  If so, rethrow the exception
190             // so that the harness gets it and deals with it.
191             if( ! testGeneratedInterrupt ) throw e;
192 
193             //reset flag in case hit this code more than once for some reason (just safety)
194             testGeneratedInterrupt = false;
195 
196             if ( theTestPassed == false )
197             {
198                 throw new RuntimeException( failureMessage );
199             }
200         }
201 
202     }//main
203 
setTimeoutTo( int seconds )204     public static synchronized void setTimeoutTo( int seconds )
205     {
206         sleepTime = seconds * 1000;
207     }
208 
pass()209     public static synchronized void pass()
210     {
211         System.out.println( "The test passed." );
212         System.out.println( "The test is over, hit  Ctl-C to stop Java VM" );
213         //first check if this is executing in main thread
214         if ( mainThread == Thread.currentThread() )
215         {
216             //Still in the main thread, so set the flag just for kicks,
217             // and throw a test passed exception which will be caught
218             // and end the test.
219             theTestPassed = true;
220             throw new TestPassedException();
221         }
222         theTestPassed = true;
223         testGeneratedInterrupt = true;
224         mainThread.interrupt();
225     }//pass()
226 
fail()227     public static synchronized void fail()
228     {
229         //test writer didn't specify why test failed, so give generic
230         fail( "it just plain failed! :-)" );
231     }
232 
fail( String whyFailed )233     public static synchronized void fail( String whyFailed )
234     {
235         System.out.println( "The test failed: " + whyFailed );
236         System.out.println( "The test is over, hit  Ctl-C to stop Java VM" );
237         //check if this called from main thread
238         if ( mainThread == Thread.currentThread() )
239         {
240             //If main thread, fail now 'cause not sleeping
241             throw new RuntimeException( whyFailed );
242         }
243         theTestPassed = false;
244         testGeneratedInterrupt = true;
245         failureMessage = whyFailed;
246         mainThread.interrupt();
247     }//fail()
248 
249 }// class OpaqueTest
250 
251 //This exception is used to exit from any level of call nesting
252 // when it's determined that the test has passed, and immediately
253 // end the test.
254 class TestPassedException extends RuntimeException
255 {
256 }
257