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