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