1 /* 2 * Copyright (c) 2006, 2014, 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 6401036 27 @summary InputVerifier shouldn't be called when requestFocus() is called on comp from another toplevel 28 @author oleg.sukhodolsky: area=awt.focus 29 @run main InputVerifierTest2 30 */ 31 32 /** 33 * InputVerifierTest2.java 34 * 35 * summary: REGRESSION: InputVerifier and JOptionPane 36 */ 37 38 import java.awt.AWTException; 39 import java.awt.BorderLayout; 40 import java.awt.Component; 41 import java.awt.Dialog; 42 import java.awt.Frame; 43 import java.awt.Point; 44 import java.awt.Robot; 45 import java.awt.TextArea; 46 47 import java.awt.event.InputEvent; 48 49 import javax.swing.InputVerifier; 50 import javax.swing.JButton; 51 import javax.swing.JComponent; 52 import javax.swing.JFrame; 53 import javax.swing.JTextField; 54 import javax.swing.JWindow; 55 56 public class InputVerifierTest2 57 { 58 59 private static void init() 60 { 61 //*** Create instructions for the user here *** 62 63 String[] instructions = 64 { 65 "This is an AUTOMATIC test, simply wait until it is done.", 66 "The result (passed or failed) will be shown in the", 67 "message window below." 68 }; 69 Sysout.createDialog( ); 70 Sysout.printInstructions( instructions ); 71 72 JFrame frame = new JFrame(); 73 frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 74 JTextField tf = new JTextField(10); 75 frame.getContentPane().add(tf); 76 77 final JWindow w = new JWindow(frame); 78 JButton btn1 = new JButton("window"); 79 btn1.setName("bnt1"); 80 w.getContentPane().add(btn1); 81 w.pack(); 82 w.setVisible(true); 83 84 frame.setSize(200, 200); 85 frame.setVisible(true); 86 87 88 Robot r = null; 89 try { 90 r = new Robot(); 91 } catch (AWTException e) { 92 InputVerifierTest2.fail(e); 93 } 94 95 96 try { 97 r.waitForIdle(); 98 mouseClickOnComp(r, tf); 99 r.waitForIdle(); 100 101 if (!tf.isFocusOwner()) { 102 throw new RuntimeException("t1 is not a focus owner"); 103 } 104 105 tf.setInputVerifier(new InputVerifier() { 106 public boolean verify(JComponent input) { 107 System.err.println("verify on " + input); 108 throw new RuntimeException("InputVerifier should not be called"); 109 } 110 }); 111 btn1.requestFocus(); 112 } catch (Exception e) { 113 InputVerifierTest2.fail(e); 114 } 115 116 InputVerifierTest2.pass(); 117 118 }//End init() 119 120 121 static void mouseClickOnComp(Robot r, Component comp) { 122 Point loc = comp.getLocationOnScreen(); 123 loc.x += comp.getWidth() / 2; 124 loc.y += comp.getHeight() / 2; 125 r.mouseMove(loc.x, loc.y); 126 r.delay(10); 127 r.mousePress(InputEvent.BUTTON1_MASK); 128 r.delay(10); 129 r.mouseRelease(InputEvent.BUTTON1_MASK); 130 } 131 132 /***************************************************** 133 * Standard Test Machinery Section 134 * DO NOT modify anything in this section -- it's a 135 * standard chunk of code which has all of the 136 * synchronisation necessary for the test harness. 137 * By keeping it the same in all tests, it is easier 138 * to read and understand someone else's test, as 139 * well as insuring that all tests behave correctly 140 * with the test harness. 141 * There is a section following this for test- 142 * classes 143 ******************************************************/ 144 private static boolean theTestPassed = false; 145 private static boolean testGeneratedInterrupt = false; 146 private static String failureMessage = ""; 147 148 private static Thread mainThread = null; 149 150 private static int sleepTime = 300000; 151 152 // Not sure about what happens if multiple of this test are 153 // instantiated in the same VM. Being static (and using 154 // static vars), it aint gonna work. Not worrying about 155 // it for now. 156 public static void main( String args[] ) throws InterruptedException 157 { 158 mainThread = Thread.currentThread(); 159 try 160 { 161 init(); 162 } 163 catch( TestPassedException e ) 164 { 165 //The test passed, so just return from main and harness will 166 // interepret this return as a pass 167 return; 168 } 169 //At this point, neither test pass nor test fail has been 170 // called -- either would have thrown an exception and ended the 171 // test, so we know we have multiple threads. 172 173 //Test involves other threads, so sleep and wait for them to 174 // called pass() or fail() 175 try 176 { 177 Thread.sleep( sleepTime ); 178 //Timed out, so fail the test 179 throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); 180 } 181 catch (InterruptedException e) 182 { 183 //The test harness may have interrupted the test. If so, rethrow the exception 184 // so that the harness gets it and deals with it. 185 if( ! testGeneratedInterrupt ) throw e; 186 187 //reset flag in case hit this code more than once for some reason (just safety) 188 testGeneratedInterrupt = false; 189 190 if ( theTestPassed == false ) 191 { 192 throw new RuntimeException( failureMessage ); 193 } 194 } 195 196 }//main 197 198 public static synchronized void setTimeoutTo( int seconds ) 199 { 200 sleepTime = seconds * 1000; 201 } 202 203 public static synchronized void pass() 204 { 205 Sysout.println( "The test passed." ); 206 Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); 207 //first check if this is executing in main thread 208 if ( mainThread == Thread.currentThread() ) 209 { 210 //Still in the main thread, so set the flag just for kicks, 211 // and throw a test passed exception which will be caught 212 // and end the test. 213 theTestPassed = true; 214 throw new TestPassedException(); 215 } 216 theTestPassed = true; 217 testGeneratedInterrupt = true; 218 mainThread.interrupt(); 219 }//pass() 220 221 public static synchronized void fail( Exception whyFailed ) 222 { 223 Sysout.println( "The test failed: " + whyFailed ); 224 Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); 225 //check if this called from main thread 226 if ( mainThread == Thread.currentThread() ) 227 { 228 //If main thread, fail now 'cause not sleeping 229 throw new RuntimeException( whyFailed ); 230 } 231 theTestPassed = false; 232 testGeneratedInterrupt = true; 233 failureMessage = whyFailed.toString(); 234 mainThread.interrupt(); 235 }//fail() 236 237 }// class InputVerifierTest2 238 239 //This exception is used to exit from any level of call nesting 240 // when it's determined that the test has passed, and immediately 241 // end the test. 242 class TestPassedException extends RuntimeException 243 { 244 } 245 246 //*********** End Standard Test Machinery Section ********** 247 248 /**************************************************** 249 Standard Test Machinery 250 DO NOT modify anything below -- it's a standard 251 chunk of code whose purpose is to make user 252 interaction uniform, and thereby make it simpler 253 to read and understand someone else's test. 254 ****************************************************/ 255 256 /** 257 This is part of the standard test machinery. 258 It creates a dialog (with the instructions), and is the interface 259 for sending text messages to the user. 260 To print the instructions, send an array of strings to Sysout.createDialog 261 WithInstructions method. Put one line of instructions per array entry. 262 To display a message for the tester to see, simply call Sysout.println 263 with the string to be displayed. 264 This mimics System.out.println but works within the test harness as well 265 as standalone. 266 */ 267 268 class Sysout 269 { 270 private static TestDialog dialog; 271 272 public static void createDialogWithInstructions( String[] instructions ) 273 { 274 dialog = new TestDialog( new Frame(), "Instructions" ); 275 dialog.printInstructions( instructions ); 276 dialog.setVisible(true); 277 println( "Any messages for the tester will display here." ); 278 } 279 280 public static void createDialog( ) 281 { 282 dialog = new TestDialog( new Frame(), "Instructions" ); 283 String[] defInstr = { "Instructions will appear here. ", "" } ; 284 dialog.printInstructions( defInstr ); 285 dialog.setVisible(true); 286 println( "Any messages for the tester will display here." ); 287 } 288 289 290 public static void printInstructions( String[] instructions ) 291 { 292 dialog.printInstructions( instructions ); 293 } 294 295 296 public static void println( String messageIn ) 297 { 298 dialog.displayMessage( messageIn ); 299 System.out.println(messageIn); 300 } 301 302 }// Sysout class 303 304 /** 305 This is part of the standard test machinery. It provides a place for the 306 test instructions to be displayed, and a place for interactive messages 307 to the user to be displayed. 308 To have the test instructions displayed, see Sysout. 309 To have a message to the user be displayed, see Sysout. 310 Do not call anything in this dialog directly. 311 */ 312 class TestDialog extends Dialog 313 { 314 315 TextArea instructionsText; 316 TextArea messageText; 317 int maxStringLength = 80; 318 319 //DO NOT call this directly, go through Sysout 320 public TestDialog( Frame frame, String name ) 321 { 322 super( frame, name ); 323 int scrollBoth = TextArea.SCROLLBARS_BOTH; 324 instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); 325 add( "North", instructionsText ); 326 327 messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); 328 add("Center", messageText); 329 330 pack(); 331 332 setVisible(true); 333 }// TestDialog() 334 335 //DO NOT call this directly, go through Sysout 336 public void printInstructions( String[] instructions ) 337 { 338 //Clear out any current instructions 339 instructionsText.setText( "" ); 340 341 //Go down array of instruction strings 342 343 String printStr, remainingStr; 344 for( int i=0; i < instructions.length; i++ ) 345 { 346 //chop up each into pieces maxSringLength long 347 remainingStr = instructions[ i ]; 348 while( remainingStr.length() > 0 ) 349 { 350 //if longer than max then chop off first max chars to print 351 if( remainingStr.length() >= maxStringLength ) 352 { 353 //Try to chop on a word boundary 354 int posOfSpace = remainingStr. 355 lastIndexOf( ' ', maxStringLength - 1 ); 356 357 if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; 358 359 printStr = remainingStr.substring( 0, posOfSpace + 1 ); 360 remainingStr = remainingStr.substring( posOfSpace + 1 ); 361 } 362 //else just print 363 else 364 { 365 printStr = remainingStr; 366 remainingStr = ""; 367 } 368 369 instructionsText.append( printStr + "\n" ); 370 371 }// while 372 373 }// for 374 375 }//printInstructions() 376 377 //DO NOT call this directly, go through Sysout 378 public void displayMessage( String messageIn ) 379 { 380 messageText.append( messageIn + "\n" ); 381 System.out.println(messageIn); 382 } 383 384 }// TestDialog class