1 /*
   2 test
   3 @bug 4799136
   4 @summary Tests that type-ahead for dialog works and doesn't block program
   5 @author Dmitry.Cherepanov@SUN.COM area=awt.focus
   6 @run applet FreezeTest.html
   7 */
   8 
   9 import java.applet.Applet;
  10 import java.awt.*;
  11 import java.lang.reflect.InvocationTargetException;
  12 import java.awt.event.*;
  13 import sun.awt.SunToolkit;
  14 
  15 /*
  16  * Tests that type-ahead doesn't block program.
  17  */
  18 
  19 public class FreezeTest extends Applet
  20 {
  21     static Frame f;
  22     static Button b;
  23     static Dialog d;
  24     static TextField tf;
  25     static Semaphore robotSema = new Semaphore();
  26     static Robot robot;
  27     static int click_count = 100;
  28     static int deliver_count = 0;
  29 
  30     public void init()
  31     {
  32         Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
  33                 public void eventDispatched(AWTEvent e) {
  34                     if (e instanceof KeyEvent){
  35                         deliver_count++;
  36                         System.err.println("key_event# "+deliver_count);
  37                     }
  38 
  39                     if (e instanceof InputEvent){
  40                         System.err.println(e.toString()+","+((InputEvent)e).getWhen());
  41                     }else{
  42                         System.err.println(e.toString());
  43                     }
  44                  }
  45             }, AWTEvent.KEY_EVENT_MASK | AWTEvent.FOCUS_EVENT_MASK);
  46 
  47         this.setLayout (new BorderLayout ());
  48 
  49         f = new Frame("frame");
  50         b = new Button("press");
  51         d = new Dialog(f, "dialog", true);
  52         tf = new TextField("");
  53         d.add(tf);
  54         d.pack();
  55 
  56         f.add(b);
  57         f.pack();
  58         b.addActionListener(new ActionListener() {
  59                 public void actionPerformed(ActionEvent e) {
  60                     System.err.println(e.toString()+","+e.getWhen());
  61                     System.err.println("B pressed");
  62                     robotSema.raise();
  63 
  64                     EventQueue.invokeLater(new Runnable() {
  65                             public void run() {
  66                                 waitTillShown(d);
  67                                 FreezeTest.this.d.toFront();
  68                                 FreezeTest.this.moveMouseOver(d);
  69                             }
  70                         });
  71                     d.setVisible(true);
  72                 }
  73             });
  74 
  75     }//End  init()
  76 
  77     public void start ()
  78     {
  79         //Get things going.  Request focus, set size, et cetera
  80         setSize (200,200);
  81         setVisible(true);
  82         validate();
  83         try {
  84             robot = new Robot();
  85         } catch (Exception e) {
  86             throw new RuntimeException("Can't create robot:" + e);
  87         }
  88 
  89         f.setVisible(true);
  90         waitTillShown(b);
  91         System.err.println("b is shown");
  92         f.toFront();
  93         moveMouseOver(f);
  94         ((SunToolkit)Toolkit.getDefaultToolkit()).realSync();
  95         makeFocused(b);
  96         ((SunToolkit)Toolkit.getDefaultToolkit()).realSync();
  97         System.err.println("b is focused");
  98 
  99         robot.keyPress(KeyEvent.VK_SPACE);
 100         robot.keyRelease(KeyEvent.VK_SPACE);
 101         try {
 102             robotSema.doWait(1000);
 103         } catch (InterruptedException ie) {
 104             throw new RuntimeException("Interrupted!");
 105         }
 106 
 107         for (int i = 0; i < click_count; i++){
 108             System.err.println("click# "+(i+1));
 109             robot.keyPress(KeyEvent.VK_SPACE);
 110             robot.delay(10);
 111             robot.keyRelease(KeyEvent.VK_SPACE);
 112             robot.delay(50);
 113         }
 114 
 115         ((SunToolkit)Toolkit.getDefaultToolkit()).realSync();
 116 
 117         int deliver_count = this.deliver_count;
 118         int expected_count = (click_count + 1) * 3;
 119 
 120         if (deliver_count != expected_count){
 121             System.err.println("deliver_count = "+deliver_count+" (!="+expected_count+")");
 122             throw new RuntimeException("incorrect behaviour");
 123         }
 124     }// start()
 125 
 126     private void moveMouseOver(Container c) {
 127         Point p = c.getLocationOnScreen();
 128         Dimension d = c.getSize();
 129         robot.mouseMove(p.x + (int)(d.getWidth()/2), p.y + (int)(d.getHeight()/2));
 130     }
 131 
 132     private void waitTillShown(Component c) {
 133         while (true) {
 134             try {
 135                 Thread.sleep(100);
 136                 c.getLocationOnScreen();
 137                 break;
 138             } catch (InterruptedException ie) {
 139                 ie.printStackTrace();
 140                 break;
 141             } catch (Exception e) {
 142             }
 143         }
 144     }
 145     private void makeFocused(Component comp) {
 146         if (comp.isFocusOwner()) {
 147             return;
 148         }
 149         final Semaphore sema = new Semaphore();
 150         final FocusAdapter fa = new FocusAdapter() {
 151                 public void focusGained(FocusEvent fe) {
 152                     sema.raise();
 153                 }
 154             };
 155         comp.addFocusListener(fa);
 156         comp.requestFocusInWindow();
 157         if (comp.isFocusOwner()) {
 158             return;
 159         }
 160         try {
 161             sema.doWait(3000);
 162         } catch (InterruptedException ie) {
 163             ie.printStackTrace();
 164         }
 165         comp.removeFocusListener(fa);
 166         if (!comp.isFocusOwner()) {
 167             throw new RuntimeException("Can't make " + comp + " focused, current owner is " + KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner());
 168         }
 169     }
 170 
 171 static class Semaphore {
 172     boolean state = false;
 173     int waiting = 0;
 174     public Semaphore() {
 175     }
 176     public synchronized void doWait() throws InterruptedException {
 177         if (state) {
 178             return;
 179         }
 180         waiting++;
 181         wait();
 182         waiting--;
 183     }
 184     public synchronized void doWait(int timeout) throws InterruptedException {
 185         if (state) {
 186             return;
 187         }
 188         waiting++;
 189         wait(timeout);
 190         waiting--;
 191     }
 192     public synchronized void raise() {
 193         state = true;
 194         if (waiting > 0) {
 195             notifyAll();
 196         }
 197     }
 198     public synchronized boolean getState() {
 199         return state;
 200     }
 201 }
 202 }// class TestDialogTypeAhead
 203 
 204 
 205 /****************************************************
 206  Standard Test Machinery
 207  DO NOT modify anything below -- it's a standard
 208   chunk of code whose purpose is to make user
 209   interaction uniform, and thereby make it simpler
 210   to read and understand someone else's test.
 211  ****************************************************/
 212 
 213 /**
 214  This is part of the standard test machinery.
 215  It creates a dialog (with the instructions), and is the interface
 216   for sending text messages to the user.
 217  To print the instructions, send an array of strings to Sysout.createDialog
 218   WithInstructions method.  Put one line of instructions per array entry.
 219  To display a message for the tester to see, simply call Sysout.println
 220   with the string to be displayed.
 221  This mimics System.out.println but works within the test harness as well
 222   as standalone.
 223  */
 224 
 225 class Sysout
 226 {
 227     private static TestDialog dialog;
 228 
 229     public static void createDialogWithInstructions( String[] instructions )
 230     {
 231         dialog = new TestDialog( new Frame(), "Instructions" );
 232         dialog.printInstructions( instructions );
 233         dialog.setVisible(true);
 234         println( "Any messages for the tester will display here." );
 235     }
 236 
 237     public static void createDialog( )
 238     {
 239         dialog = new TestDialog( new Frame(), "Instructions" );
 240         String[] defInstr = { "Instructions will appear here. ", "" } ;
 241         dialog.printInstructions( defInstr );
 242         dialog.setVisible(true);
 243         println( "Any messages for the tester will display here." );
 244     }
 245 
 246 
 247     public static void printInstructions( String[] instructions )
 248     {
 249         dialog.printInstructions( instructions );
 250     }
 251 
 252 
 253     public static void println( String messageIn )
 254     {
 255         dialog.displayMessage( messageIn );
 256     }
 257 
 258 }// Sysout  class
 259 
 260 /**
 261   This is part of the standard test machinery.  It provides a place for the
 262    test instructions to be displayed, and a place for interactive messages
 263    to the user to be displayed.
 264   To have the test instructions displayed, see Sysout.
 265   To have a message to the user be displayed, see Sysout.
 266   Do not call anything in this dialog directly.
 267   */
 268 class TestDialog extends Dialog
 269 {
 270 
 271     TextArea instructionsText;
 272     TextArea messageText;
 273     int maxStringLength = 80;
 274 
 275     //DO NOT call this directly, go through Sysout
 276     public TestDialog( Frame frame, String name )
 277     {
 278         super( frame, name );
 279         int scrollBoth = TextArea.SCROLLBARS_BOTH;
 280         instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
 281         add( "North", instructionsText );
 282 
 283         messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
 284         add("Center", messageText);
 285 
 286         pack();
 287 
 288         show();
 289     }// TestDialog()
 290 
 291     //DO NOT call this directly, go through Sysout
 292     public void printInstructions( String[] instructions )
 293     {
 294         //Clear out any current instructions
 295         instructionsText.setText( "" );
 296 
 297         //Go down array of instruction strings
 298 
 299         String printStr, remainingStr;
 300         for( int i=0; i < instructions.length; i++ )
 301         {
 302             //chop up each into pieces maxSringLength long
 303             remainingStr = instructions[ i ];
 304             while( remainingStr.length() > 0 )
 305             {
 306                 //if longer than max then chop off first max chars to print
 307                 if( remainingStr.length() >= maxStringLength )
 308                 {
 309                     //Try to chop on a word boundary
 310                     int posOfSpace = remainingStr.
 311                         lastIndexOf( ' ', maxStringLength - 1 );
 312 
 313                     if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
 314 
 315                     printStr = remainingStr.substring( 0, posOfSpace + 1 );
 316                     remainingStr = remainingStr.substring( posOfSpace + 1 );
 317                 }
 318                 //else just print
 319                 else
 320                 {
 321                     printStr = remainingStr;
 322                     remainingStr = "";
 323                 }
 324 
 325                 instructionsText.append( printStr + "\n" );
 326 
 327             }// while
 328 
 329         }// for
 330 
 331     }//printInstructions()
 332 
 333     //DO NOT call this directly, go through Sysout
 334     public void displayMessage( String messageIn )
 335     {
 336         messageText.append( messageIn + "\n" );
 337         System.out.println(messageIn);
 338     }
 339 
 340 }// TestDialog  class