1 /*
   2  * Copyright (c) 2008, 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 4452384
  27   @summary Tests that non-focusable windows doesn't generate any focus events when accessed.
  28   @author Denis.Mikhalkin: area=awt.focus
  29   @run main NoEventsTest
  30 */
  31 
  32 import java.awt.*;
  33 import java.awt.event.*;
  34 import java.util.*;
  35 
  36 public class NoEventsTest extends Frame {
  37     public static final int DEF_WIDTH = 400,
  38         DEF_HEIGHT = 300,
  39         DEF_TOP = 1,
  40         DEF_LEFT = 100,
  41         DEF_ROW = 0,
  42         DEF_COL = 0;
  43     static boolean automatic = true;
  44     static Window[] windows;
  45     static Frame main_frame, jumpingFrame;
  46     static Button focus_button;
  47     static Robot robot;
  48     static void pause(int timeout) {
  49         Toolkit.getDefaultToolkit().sync();
  50         robot.waitForIdle();
  51         robot.delay(100);
  52     }
  53     static GlobalListener listener;
  54     public static void main(String[] args) {
  55 
  56         listener = new GlobalListener();
  57         Toolkit.getDefaultToolkit().addAWTEventListener(listener,
  58                                                         AWTEvent.FOCUS_EVENT_MASK |
  59                                                         AWTEvent.WINDOW_EVENT_MASK);
  60         try{
  61             robot = new Robot();
  62         } catch(Exception e) {}
  63         // Create several pairs - focusable Frame with focusable component(button) and non-focusable:
  64         // window, resizable frame, non-resizable frame, dialog, non-resiable dialog
  65         main_frame = new Frame("focusable frame");
  66         focus_button = new Button("button to focus");
  67         main_frame.add(focus_button);
  68         main_frame.pack();
  69         main_frame.setVisible(true);
  70         main_frame.setLocation(10, 600);
  71         main_frame.addWindowListener(new WindowAdapter() {
  72                 public void windowClosing(WindowEvent e) {
  73                     listener.report();
  74                     System.exit(0);
  75                 }
  76             });
  77 
  78         jumpingFrame = new Frame("Jumping frame");
  79         jumpingFrame.setBounds(DEF_LEFT, DEF_TOP, DEF_WIDTH, DEF_HEIGHT);
  80 
  81         windows = new Window[7];
  82         windows[0] = new TestWindow(0, 0, false, main_frame);
  83         //windows[1] = new TestWindow(2, 1, true, main_frame);
  84         windows[2] = new NoEventsTest(1, 0, false, true);
  85         windows[3] = new NoEventsTest(2, 0, false, false);
  86         //windows[4] = new Test(3, 0, true, true);
  87         windows[5] = new TestDialog(0, 1, false, true, main_frame);
  88         windows[6] = new TestDialog(1, 1, false, false, main_frame);
  89         if (!automatic) {
  90             int windowInd;
  91             for (windowInd = 0; windowInd < windows.length; windowInd++) {
  92                 if (windows[windowInd] != null) {
  93                     windows[windowInd].setVisible(true);
  94                 }
  95             }
  96         }
  97         // Run the test
  98         // 1. Click on all controls, check for no focus events for non-focusable, right focus events for focusable
  99         // 2. Perform some action with control, check if it works
 100         if (automatic) {
 101             int windowInd;
 102             for (windowInd = 0; windowInd < windows.length; windowInd++) {
 103                 if (windows[windowInd] != null) {
 104                     windows[windowInd].setVisible(true);
 105                     focus_button.requestFocus();
 106                     pause(1000);
 107 
 108                     // Verify that click on non-focusable window causes no focus lost on active window
 109                     performFocusClick(windows[windowInd]);
 110                     focus_button.requestFocus();
 111                     pause(500);
 112                     performActionClick(windows[windowInd]);
 113 
 114                     // Verify that toFront, toBack doesn't cause non-focusable window to become active
 115                     jumpingFrame.setVisible(true);
 116                     pause(1000);
 117                       jumpingFrame.toBack();
 118                       pause(500);
 119                       jumpingFrame.toFront();
 120                       pause(500);
 121                       windows[windowInd].toBack();
 122                       pause(500);
 123                       windows[windowInd].toFront();
 124                       pause(500);
 125 
 126                     // Verify that iconifiyng/deiconfiying and
 127                     // zooming/unzooming doesn't cause non-focusable
 128                     // window to become active
 129                     if (windows[windowInd] instanceof Frame) {
 130                         Frame toTest = (Frame)windows[windowInd];
 131                         // Deiconification currently doesn't work!
 132 //                        toTest.setExtendedState(Frame.ICONIFIED);
 133 //                        pause(500);
 134 //                        toTest.setExtendedState(Frame.NORMAL);
 135                         pause(500);
 136                         toTest.setExtendedState(Frame.MAXIMIZED_BOTH);
 137                         pause(500);
 138                         toTest.setExtendedState(Frame.NORMAL);
 139                     }
 140 
 141                     windows[windowInd].dispose();
 142                     jumpingFrame.dispose();
 143                 }
 144             }
 145             pause(1000);
 146             System.err.println("Test finished.");
 147             if (!listener.report()) {
 148                 throw new RuntimeException("Test Failed. See error stream output for details");
 149             }
 150         }
 151     }
 152     static void performFocusClick(Window parent) {
 153         if (parent == null) {
 154             return;
 155         }
 156         for (int compInd = 0; compInd < parent.getComponentCount(); compInd++) {
 157             Component child = parent.getComponent(compInd);
 158             if (child instanceof TestPanel) {
 159                 TestPanel pan = (TestPanel)child;
 160                 pan.performFocusClicks(robot);
 161                 pause(100);
 162             }
 163         }
 164     }
 165     static void performActionClick(Window parent) {
 166         if (parent == null) {
 167             return;
 168         }
 169         for (int compInd = 0; compInd < parent.getComponentCount(); compInd++) {
 170             Component child = parent.getComponent(compInd);
 171             if (child instanceof TestPanel) {
 172                 TestPanel pan = (TestPanel)child;
 173                 pan.performActionClicks(robot);
 174                 pause(100);
 175             }
 176         }
 177     }
 178     public NoEventsTest(int row, int col, boolean focusable, boolean resizable) {
 179         super("Frame" + row + "" + col);
 180         TestPanel panel = new TestPanel(row, col);
 181         if (NoEventsTest.automatic) {
 182             row = NoEventsTest.DEF_ROW;
 183             col = NoEventsTest.DEF_COL;
 184         }
 185         setName(getTitle());
 186         add("Center", panel);
 187         Label l = new Label(getClass().getSuperclass().getName() + ", " + (focusable?"focusable":"non-focusable") +
 188                             ", " + (resizable?"resizable":"non-resizable"));
 189         l.setBackground(Color.green);
 190         add("North", l);
 191         setBounds(NoEventsTest.DEF_LEFT + DEF_WIDTH*col, DEF_TOP + DEF_HEIGHT*row, DEF_WIDTH, DEF_HEIGHT);
 192         if (!focusable) {
 193             setFocusableWindowState(false);
 194         }
 195         if (!resizable) {
 196             setResizable(false);
 197         }
 198 //        setVisible(true);
 199     }
 200 }
 201 class TestWindow extends Window {
 202     public TestWindow(int row, int col, boolean focusable, Frame owner) {
 203         super(owner);
 204         setName("Window" + row + "" + col);
 205         TestPanel panel = new TestPanel(row, col);
 206         if (NoEventsTest.automatic) {
 207             row = NoEventsTest.DEF_ROW;
 208             col = NoEventsTest.DEF_COL;
 209         }
 210 
 211         add("Center", panel);
 212         Label l = new Label(getClass().getSuperclass().getName() + ", " + (focusable?"focusable":"non-focusable") +
 213                             ", " + (false?"resizable":"non-resizable"));
 214         l.setBackground(Color.green);
 215         add("North", l);
 216 
 217         setBounds(NoEventsTest.DEF_LEFT + NoEventsTest.DEF_WIDTH*col, NoEventsTest.DEF_TOP + NoEventsTest.DEF_HEIGHT*row, NoEventsTest.DEF_WIDTH, NoEventsTest.DEF_HEIGHT);
 218         if (!focusable) {
 219             setFocusableWindowState(false);
 220         }
 221 //        setVisible(true);
 222     }
 223 }
 224 class TestDialog extends Dialog {
 225     public TestDialog(int row, int col, boolean focusable, boolean resizable, Frame owner) {
 226         super(owner);
 227         setName("Dialog" + row + "" + col);
 228         TestPanel panel = new TestPanel(row, col);
 229         if (NoEventsTest.automatic) {
 230             row = NoEventsTest.DEF_ROW;
 231             col = NoEventsTest.DEF_COL;
 232         }
 233 
 234         add("Center", panel);
 235         Label l = new Label(getClass().getSuperclass().getName() + ", " + (focusable?"focusable":"non-focusable") +
 236                             ", " + (resizable?"resizable":"non-resizable"));
 237         l.setBackground(Color.green);
 238         add("North", l);
 239 
 240         setBounds(NoEventsTest.DEF_LEFT + NoEventsTest.DEF_WIDTH*col, NoEventsTest.DEF_TOP + NoEventsTest.DEF_HEIGHT*row, NoEventsTest.DEF_WIDTH, NoEventsTest.DEF_HEIGHT);
 241         if (!focusable) {
 242             setFocusableWindowState(false);
 243         }
 244         if (!resizable) {
 245             setResizable(false);
 246         }
 247 //        setVisible(true);
 248     }
 249 }
 250 
 251 class TestPanel extends Panel {
 252 
 253     void clickComponent(Component comp, Robot robot) {
 254         if (comp instanceof Choice) {
 255             return;
 256         }
 257         Point compLoc = comp.getLocationOnScreen();
 258         Dimension size = comp.getSize();
 259         robot.mouseMove(compLoc.x + size.width/2, compLoc.y + size.height/2);
 260         robot.mousePress(InputEvent.BUTTON1_MASK);
 261         robot.mouseRelease(InputEvent.BUTTON1_MASK);
 262     }
 263     void performFocusClicks(Robot robot) {
 264         for (int childInd = 0; childInd < getComponentCount(); childInd++) {
 265             performFocusClick(getComponent(childInd), robot);
 266         }
 267     }
 268     void performFocusClick(Component comp, Robot robot) {
 269         clickComponent(comp, robot);
 270     }
 271 
 272     void performActionClicks(Robot robot) {
 273         for (int childInd = 0; childInd < getComponentCount(); childInd++) {
 274             performActionClick(getComponent(childInd), robot);
 275         }
 276     }
 277     void performActionClick(Component comp, Robot robot) {
 278     }
 279 
 280     public TestPanel(int row, int col) {
 281         setLayout(new FlowLayout());
 282         Button b;
 283         add(b = new Button("press"+ row + "" + col));
 284         b.setName(b.getLabel());
 285 //         b.addMouseListener(new MouseAdapter() {
 286 //                 public void mousePressed(MouseEvent e) {
 287 //                     System.err.println(e);
 288 //                 }
 289 //             });
 290         TextField t;
 291         add(t = new TextField("text" + row + "" + col));
 292         t.setName(t.getText());
 293 
 294         java.awt.List list = new java.awt.List();
 295         add(list);
 296         list.setName("list");
 297         list.add("one");
 298         list.add("two");
 299         list.add("three");
 300         list.setMultipleMode(true);
 301         list.setName("list" + row + "" + col);
 302 
 303         Checkbox check = new Checkbox("checker");
 304         add(check);
 305         check.setName("check" + row + "" + col);
 306 
 307         Choice choice = new Choice();
 308         choice.add("one");
 309         choice.add("two");
 310         choice.add("three");
 311         add(choice);
 312         choice.setName("choice" + row + "" + col);
 313 
 314         Canvas can = new Canvas() {
 315                 public Dimension getPreferredSize() {
 316                     return new Dimension(10, 10);
 317                 }
 318             };
 319         can.setBackground(Color.blue);
 320         add(can);
 321         can.setName("canvas" + row + "" + col);
 322 
 323         TextArea ta = new TextArea("text\ntttt\naaaa\nwwwww\nqqqqqq\neeeeee\nrrrrrr\nyyyyyy\nuuuuu", 3, 5);
 324         add(ta);
 325         ta.setName("textarea" + row + "" + col);
 326 
 327         Scrollbar bar = new Scrollbar(Scrollbar.HORIZONTAL);
 328         add(bar);
 329         bar.setName("scrollbar" + row + "" + col);
 330 
 331         CheckboxGroup group = new CheckboxGroup();
 332         Checkbox ch1 = new Checkbox("one", group, true);
 333         Checkbox ch2 = new Checkbox("two", group, false);
 334         add(ch1);
 335         add(ch2);
 336         ch1.setName("checkbox1 " + row + "" + col);
 337         ch2.setName("checkbox2 " + row + "" + col);
 338 
 339 
 340         ScrollPane pane = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS);
 341         add(pane);
 342         Button bigButton = new Button("abc") {
 343                 public Dimension getPreferredSize() {
 344                     return new Dimension(100, 100);
 345                 }
 346             };
 347         pane.add(bigButton);
 348         bigButton.setName("bigbutton" + row + "" + col);
 349     }
 350 }
 351 
 352 class GlobalListener implements AWTEventListener {
 353     java.util.List errors = new java.util.LinkedList();
 354     public boolean report() {
 355         if (errors.size() != 0) {
 356             System.err.println("Test FAILED");
 357         } else {
 358             System.err.println("Test PASSED");
 359             return true;
 360         }
 361         ListIterator iter = errors.listIterator();
 362         while (iter.hasNext()) {
 363             System.err.println(iter.next());
 364         }
 365         return false;
 366     }
 367     public GlobalListener() {
 368     }
 369     Window getWindowParent(Component comp) {
 370         while (comp != null && !(comp instanceof Window)) {
 371             comp = comp.getParent();
 372         }
 373         return (Window)comp;
 374     }
 375     void reportError(AWTEvent e, String message) {
 376         String error = "ERROR: " + message + " : " + e;
 377         errors.add(error);
 378         System.err.println(error);
 379     }
 380     public void eventDispatched(AWTEvent e) {
 381         Component comp = (Component)e.getSource();
 382         Window parent = getWindowParent(comp);
 383         if (!(e instanceof WindowEvent || e instanceof FocusEvent)) {
 384             System.err.println("Strange event " + e);
 385         }
 386 
 387         // Skip WINDOW_OPENED
 388         if (e.getID() == WindowEvent.WINDOW_CLOSING) {
 389             System.err.println(e);
 390         }
 391         switch (e.getID()) {
 392           case WindowEvent.WINDOW_OPENED:
 393           case WindowEvent.WINDOW_CLOSING:
 394           case WindowEvent.WINDOW_CLOSED:
 395           case WindowEvent.WINDOW_ICONIFIED:
 396           case WindowEvent.WINDOW_DEICONIFIED:
 397           case WindowEvent.WINDOW_STATE_CHANGED:
 398             return;
 399           case WindowEvent.WINDOW_LOST_FOCUS: {
 400               WindowEvent we = (WindowEvent)e;
 401               if (we.getOppositeWindow() != null && !we.getOppositeWindow().getFocusableWindowState()) {
 402                   reportError(e, "frame lost focus because of non-focusable window");
 403               }
 404               break;
 405           }
 406         }
 407         // Check that Window owner is focusable
 408         if (!parent.getFocusableWindowState()) {
 409             reportError(e, "focus event for component in non-focusable window " + parent.getName());
 410         }
 411         if (!comp.isFocusable()) {
 412             reportError(e, "focus event for non-focusable component");
 413         }
 414 //         if (e instanceof WindowEvent || e instanceof FocusEvent) {
 415 // //             System.err.println(e);
 416 //         }
 417     }
 418 }