1 /* 2 test 3 @bug 5028014 4 @summary Focus request & mouse click performed nearly synchronously shouldn't lead to a focus race. 5 @author anton.tarasov@sun.com: area=awt-focus 6 @run applet MouseClickRequestFocusRaceTest.html 7 */ 8 9 import java.awt.*; 10 import javax.swing.*; 11 import java.awt.event.*; 12 import java.applet.Applet; 13 14 public class MouseClickRequestFocusRaceTest extends Applet { 15 Robot robot; 16 JFrame frame1 = new JFrame("Frame-1") { 17 public String toString() { return "Frame-1";} 18 }; 19 JFrame frame2 = new JFrame("Frame-2") { 20 public String toString() { return "Frame-2";} 21 }; 22 JButton button1 = new JButton("button-1") { 23 public String toString() { return "button-1";} 24 }; 25 JButton button2 = new JButton("button-2") { 26 public String toString() { return "button-2";} 27 }; 28 JPopupMenu popup = new JPopupMenu(); 29 30 public static void main(String[] args) { 31 MouseClickRequestFocusRaceTest app = new MouseClickRequestFocusRaceTest(); 32 app.init(); 33 app.start(); 34 } 35 36 public void init() { 37 try { 38 robot = new Robot(); 39 } catch (AWTException e) { 40 throw new RuntimeException("Error: unable to create robot", e); 41 } 42 // Create instructions for the user here, as well as set up 43 // the environment -- set the layout manager, add buttons, 44 // etc. 45 this.setLayout (new BorderLayout ()); 46 Sysout.createDialogWithInstructions(new String[] 47 {"Automatic test. Simply wait until it is done." 48 }); 49 } 50 51 public void start() { 52 frame1.add(button1); 53 frame2.add(button2); 54 frame1.setBounds(0, 0, 200, 300); 55 frame2.setBounds(300, 0, 200, 300); 56 frame1.setLayout(new FlowLayout()); 57 frame2.setLayout(new FlowLayout()); 58 59 popup.add(new JMenuItem("black")); 60 popup.add(new JMenuItem("yellow")); 61 popup.add(new JMenuItem("white")); 62 63 frame1.add(popup); 64 65 frame1.addMouseListener(new MouseAdapter() { 66 void popup(MouseEvent e) { 67 if (e.isPopupTrigger()) { 68 Point loc = button1.getLocation(); 69 popup.show(button1, e.getX() - loc.x, e.getY() - loc.y); 70 } 71 } 72 public void mousePressed(MouseEvent e) { 73 popup(e); 74 } 75 public void mouseReleased(MouseEvent e) { 76 popup(e); 77 } 78 }); 79 80 frame2.addMouseListener(new MouseAdapter() { 81 public void mousePressed(MouseEvent e) { 82 button1.requestFocusInWindow(); 83 } 84 }); 85 86 frame2.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 87 88 frame1.setVisible(true); 89 frame2.setVisible(true); 90 // ((SunToolkit)Toolkit.getDefaultToolkit()).realSync(); 91 robot.delay(1000); 92 93 test(); 94 } 95 96 public void test() { 97 // Right click Frame-1 98 robot.mouseMove(frame1.getLocation().x + 100, frame1.getLocation().y + 200); 99 robot.mousePress(InputEvent.BUTTON3_MASK); 100 robot.delay(100); 101 robot.mouseRelease(InputEvent.BUTTON3_MASK); 102 103 // ((SunToolkit)Toolkit.getDefaultToolkit()).realSync(); 104 robot.delay(1000); 105 106 // Left click Frame-2 107 robot.mouseMove(frame2.getLocation().x + 100, frame1.getLocation().y + 200); 108 robot.mousePress(InputEvent.BUTTON1_MASK); 109 robot.delay(100); 110 robot.mouseRelease(InputEvent.BUTTON1_MASK); 111 112 // ((SunToolkit)Toolkit.getDefaultToolkit()).realSync(); 113 robot.delay(1000); 114 115 JComponent focusOwner = (JComponent)KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); 116 JFrame focusedWindow = (JFrame)KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow(); 117 118 Sysout.println("focus owner: " + focusOwner); 119 Sysout.println("focused window: " + focusedWindow); 120 121 // Verify that the focused window is the ancestor of the focus owner 122 if (!focusedWindow.isAncestorOf(focusOwner)) { 123 throw new TestFailedException("The focus owner is not in the focused window!"); 124 } 125 126 // Try to close native focused window 127 robot.keyPress(KeyEvent.VK_ALT); 128 robot.keyPress(KeyEvent.VK_F4); 129 robot.keyRelease(KeyEvent.VK_F4); 130 robot.keyRelease(KeyEvent.VK_ALT); 131 132 // ((SunToolkit)Toolkit.getDefaultToolkit()).realSync(); 133 robot.delay(1000); 134 135 // Verify that the Java focused window really mapped the native focused window. 136 if (focusedWindow.isVisible()) { 137 throw new TestFailedException("The focused window is different on Java and on the native level."); 138 } 139 } 140 141 class TestFailedException extends RuntimeException { 142 public TestFailedException(String cause) { 143 super("Test failed."); 144 Sysout.println(cause); 145 } 146 } 147 } 148 149 /**************************************************** 150 Standard Test Machinery 151 DO NOT modify anything below -- it's a standard 152 chunk of code whose purpose is to make user 153 interaction uniform, and thereby make it simpler 154 to read and understand someone else's test. 155 ****************************************************/ 156 157 /** 158 This is part of the standard test machinery. 159 It creates a dialog (with the instructions), and is the interface 160 for sending text messages to the user. 161 To print the instructions, send an array of strings to Sysout.createDialog 162 WithInstructions method. Put one line of instructions per array entry. 163 To display a message for the tester to see, simply call Sysout.println 164 with the string to be displayed. 165 This mimics System.out.println but works within the test harness as well 166 as standalone. 167 */ 168 169 class Sysout 170 { 171 static TestDialog dialog; 172 173 public static void createDialogWithInstructions( String[] instructions ) 174 { 175 dialog = new TestDialog( new Frame(), "Instructions" ); 176 dialog.printInstructions( instructions ); 177 // dialog.setVisible(true); 178 println( "Any messages for the tester will display here." ); 179 } 180 181 public static void createDialog( ) 182 { 183 dialog = new TestDialog( new Frame(), "Instructions" ); 184 String[] defInstr = { "Instructions will appear here. ", "" } ; 185 dialog.printInstructions( defInstr ); 186 // dialog.setVisible(true); 187 println( "Any messages for the tester will display here." ); 188 } 189 190 191 public static void printInstructions( String[] instructions ) 192 { 193 dialog.printInstructions( instructions ); 194 } 195 196 197 public static void println( String messageIn ) 198 { 199 dialog.displayMessage( messageIn ); 200 } 201 202 }// Sysout class 203 204 /** 205 This is part of the standard test machinery. It provides a place for the 206 test instructions to be displayed, and a place for interactive messages 207 to the user to be displayed. 208 To have the test instructions displayed, see Sysout. 209 To have a message to the user be displayed, see Sysout. 210 Do not call anything in this dialog directly. 211 */ 212 class TestDialog extends Dialog 213 { 214 215 TextArea instructionsText; 216 TextArea messageText; 217 int maxStringLength = 80; 218 219 //DO NOT call this directly, go through Sysout 220 public TestDialog( Frame frame, String name ) 221 { 222 super( frame, name ); 223 int scrollBoth = TextArea.SCROLLBARS_BOTH; 224 instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); 225 add( "North", instructionsText ); 226 227 messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); 228 add("Center", messageText); 229 230 pack(); 231 232 // setVisible(true); 233 }// TestDialog() 234 235 //DO NOT call this directly, go through Sysout 236 public void printInstructions( String[] instructions ) 237 { 238 //Clear out any current instructions 239 instructionsText.setText( "" ); 240 241 //Go down array of instruction strings 242 243 String printStr, remainingStr; 244 for( int i=0; i < instructions.length; i++ ) 245 { 246 //chop up each into pieces maxSringLength long 247 remainingStr = instructions[ i ]; 248 while( remainingStr.length() > 0 ) 249 { 250 //if longer than max then chop off first max chars to print 251 if( remainingStr.length() >= maxStringLength ) 252 { 253 //Try to chop on a word boundary 254 int posOfSpace = remainingStr. 255 lastIndexOf( ' ', maxStringLength - 1 ); 256 257 if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; 258 259 printStr = remainingStr.substring( 0, posOfSpace + 1 ); 260 remainingStr = remainingStr.substring( posOfSpace + 1 ); 261 } 262 //else just print 263 else 264 { 265 printStr = remainingStr; 266 remainingStr = ""; 267 } 268 269 instructionsText.append( printStr + "\n" ); 270 271 }// while 272 273 }// for 274 275 }//printInstructions() 276 277 //DO NOT call this directly, go through Sysout 278 public void displayMessage( String messageIn ) 279 { 280 messageText.append( messageIn + "\n" ); 281 System.out.println(messageIn); 282 } 283 284 }// TestDialog class