1 /*
   2  * Copyright (c) 2007, 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 import java.awt.BorderLayout;
  25 import java.awt.Canvas;
  26 import java.awt.EventQueue;
  27 import java.awt.Frame;
  28 import java.awt.event.FocusAdapter;
  29 import java.awt.event.FocusEvent;
  30 import java.awt.event.InputEvent;
  31 import java.awt.event.KeyAdapter;
  32 import java.awt.event.KeyEvent;
  33 import java.awt.event.MouseEvent;
  34 
  35 import static jdk.test.lib.Asserts.assertTrue;
  36 
  37 /*
  38  * NOTE: this is no intentionally a manual test (i.e. has no test tag) because
  39  * even on Windows, the various tested key-combination may get partially
  40  * intercepted by other applications and this can leave the whole system in an
  41  * inconsistent state. For example on my Windows machine with Intel Graphics
  42  * the key combinations "Ctl-Alt-F11" and "Ctl-Alt-F12" triggers some Intel
  43  * Graphics utilities by default. If the test is run in such an environment,
  44  * some key events of the test are intercepted by those utilities with the
  45  * result that the test fails and no more keyboard input will be possible at
  46  * all.
  47  *
  48  * To execute the test add a '@' before the 'test' keyword below to make it a tag.
  49  */
  50 
  51 /*
  52  * test 8155742
  53  *
  54  * @summary Make sure that modifier key mask is set when robot press
  55  *          some key with one or more modifiers.
  56  * @library /lib/testlibrary/
  57  * @library /test/lib
  58  * @build ExtendedRobot
  59  * @key headful
  60  * @run main/timeout=600 ModifierRobotEnhancedKeyTest
  61  */
  62 
  63 public class ModifierRobotEnhancedKeyTest extends KeyAdapter {
  64 
  65     private boolean focusGained = false;
  66     private boolean startTest = false;
  67     private ExtendedRobot robot;
  68     private Frame frame;
  69     private Canvas canvas;
  70 
  71     private volatile boolean tempPress = false;
  72 
  73     private int[] textKeys, modifierKeys, inputMasks;
  74     private boolean[] modifierStatus, textStatus;
  75 
  76     private final static int waitDelay = 5000;
  77     private Object tempLock = new Object();
  78     private Object keyLock = new Object();
  79 
  80     public static void main(String[] args) throws Exception {
  81         String os = System.getProperty("os.name").toLowerCase();
  82         if (!os.contains("windows")) {
  83             System.out.println("*** this test is for windows only because some of the tested key combinations " +
  84                                "might be caught by the os and therefore don't reach the canvas ***");
  85             return;
  86         }
  87 
  88         ModifierRobotEnhancedKeyTest test = new ModifierRobotEnhancedKeyTest();
  89         test.doTest();
  90     }
  91 
  92     public ModifierRobotEnhancedKeyTest() throws Exception {
  93         modifierKeys =  new int[4];
  94         modifierKeys[0] = KeyEvent.VK_SHIFT;
  95         modifierKeys[1] = KeyEvent.VK_CONTROL;
  96         modifierKeys[2] = KeyEvent.VK_ALT;
  97         modifierKeys[3] = KeyEvent.VK_ALT_GRAPH;
  98 
  99         inputMasks = new int[4];
 100         inputMasks[0] =  InputEvent.SHIFT_MASK;
 101         inputMasks[1] =  InputEvent.CTRL_MASK;
 102         inputMasks[2] =  InputEvent.ALT_MASK;
 103         inputMasks[3] =  InputEvent.ALT_GRAPH_MASK;
 104 
 105         modifierStatus = new boolean[modifierKeys.length];
 106 
 107         textKeys = new int[6];
 108         textKeys[0] = KeyEvent.VK_A;
 109         textKeys[1] = KeyEvent.VK_S;
 110         textKeys[2] = KeyEvent.VK_DELETE;
 111         textKeys[3] = KeyEvent.VK_HOME;
 112         textKeys[4] = KeyEvent.VK_F12;
 113         textKeys[5] = KeyEvent.VK_LEFT;
 114 
 115         textStatus = new boolean[textKeys.length];
 116 
 117         EventQueue.invokeAndWait( () -> { initializeGUI(); });
 118     }
 119 
 120     public void keyPressed(KeyEvent event) {
 121 
 122         tempPress = true;
 123         synchronized (tempLock) { tempLock.notifyAll(); }
 124 
 125         if (! startTest) {
 126             return;
 127         }
 128         for (int x = 0; x < inputMasks.length; x++) {
 129             if ((event.getModifiers() & inputMasks[x]) != 0) {
 130                 System.out.println("Modifier set: " + event.getKeyModifiersText(inputMasks[x]));
 131                 modifierStatus[x] = true;
 132             }
 133         }
 134         for (int x = 0; x < textKeys.length; x++) {
 135             if (event.getKeyCode() == textKeys[x]) {
 136                 System.out.println("Text set: " + event.getKeyText(textKeys[x]));
 137                 textStatus[x] = true;
 138             }
 139         }
 140 
 141         synchronized (keyLock) { keyLock.notifyAll(); }
 142     }
 143 
 144     private void initializeGUI() {
 145         frame = new Frame("Test frame");
 146         canvas = new Canvas();
 147         canvas.addFocusListener(new FocusAdapter() {
 148             public void focusGained(FocusEvent event) { focusGained = true; }
 149         });
 150         canvas.addKeyListener(this);
 151         frame.setLayout(new BorderLayout());
 152         frame.add(canvas);
 153         frame.setSize(200, 200);
 154         frame.setVisible(true);
 155     }
 156 
 157     public void doTest() throws Exception {
 158         robot = new ExtendedRobot();
 159 
 160         robot.mouseMove((int) frame.getLocationOnScreen().getX() + frame.getSize().width / 2,
 161                         (int) frame.getLocationOnScreen().getY() + frame.getSize().height / 2);
 162         robot.click(MouseEvent.BUTTON1_MASK);
 163         robot.waitForIdle();
 164 
 165         assertTrue(focusGained, "FAIL: Canvas gained focus!");
 166 
 167         for (int i = 0; i < modifierKeys.length; i++) {
 168             for (int j = 0; j < textKeys.length; j++) {
 169                 tempPress = false;
 170                 robot.keyPress(modifierKeys[i]);
 171                 robot.waitForIdle();
 172                 if (! tempPress) {
 173                     synchronized (tempLock) { tempLock.wait(waitDelay); }
 174                 }
 175                 assertTrue(tempPress, "FAIL: keyPressed triggered for i=" + i);
 176 
 177                 resetStatus();
 178                 startTest = true;
 179                 robot.keyPress(textKeys[j]);
 180                 robot.waitForIdle();
 181                 if (! modifierStatus[i] || ! textStatus[j]) {
 182                     synchronized (keyLock) { keyLock.wait(waitDelay); }
 183                 }
 184 
 185 
 186                 assertTrue(modifierStatus[i] && textStatus[j],
 187                         "FAIL: KeyEvent not proper!"+
 188                         "Key checked: i=" + i + "; j=" + j+
 189                         "ModifierStatus = " + modifierStatus[i]+
 190                         "TextStatus = " + textStatus[j]);
 191                 startTest = false;
 192                 robot.keyRelease(textKeys[j]);
 193                 robot.waitForIdle();
 194                 robot.keyRelease(modifierKeys[i]);
 195                 robot.waitForIdle();
 196             }
 197         }
 198 
 199         for (int i = 0; i < modifierKeys.length; i++) {
 200             for (int j = i + 1; j < modifierKeys.length; j++) {
 201                 for (int k = 0; k < textKeys.length; k++) {
 202                     tempPress = false;
 203                     robot.keyPress(modifierKeys[i]);
 204                     robot.waitForIdle();
 205                     if (! tempPress) {
 206                         synchronized (tempLock) { tempLock.wait(waitDelay); }
 207                     }
 208 
 209                     assertTrue(tempPress, "FAIL: MultiKeyTest: keyPressed triggered for i=" + i);
 210 
 211                     tempPress = false;
 212                     robot.keyPress(modifierKeys[j]);
 213                     robot.waitForIdle();
 214                     if (! tempPress) {
 215                         synchronized (tempLock) { tempLock.wait(waitDelay); }
 216                     }
 217                     assertTrue(tempPress, "FAIL: MultiKeyTest keyPressed triggered for j=" + j);
 218 
 219                     resetStatus();
 220                     startTest = true;
 221                     robot.keyPress(textKeys[k]);
 222                     robot.waitForIdle();
 223                     if (! modifierStatus[i] || ! modifierStatus[j] || ! textStatus[k]) {
 224                         synchronized (keyLock) {
 225                             keyLock.wait(waitDelay);
 226                         }
 227                     }
 228                     assertTrue(modifierStatus[i] && modifierStatus[j] && textStatus[k],
 229                             "FAIL: KeyEvent not proper!"+
 230                             "Key checked: i=" + i + "; j=" + j + "; k=" + k+
 231                             "Modifier1Status = " + modifierStatus[i]+
 232                             "Modifier2Status = " + modifierStatus[j]+
 233                             "TextStatus = " + textStatus[k]);
 234 
 235                     startTest = false;
 236                     robot.keyRelease(textKeys[k]);
 237                     robot.waitForIdle();
 238                     robot.keyRelease(modifierKeys[j]);
 239                     robot.waitForIdle();
 240                     robot.keyRelease(modifierKeys[i]);
 241                     robot.waitForIdle();
 242                 }
 243             }
 244         }
 245 
 246         frame.dispose();
 247     }
 248 
 249     private void resetStatus() {
 250         for (int i = 0; i < modifierStatus.length; i++) {
 251             modifierStatus[i] = false;
 252         }
 253         for (int i = 0; i < textStatus.length; i++) {
 254             textStatus[i] = false;
 255         }
 256     }
 257 
 258 }