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