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.testlibrary.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  * @build ExtendedRobot
  58  * @key headful
  59  * @run main/timeout=600 ModifierRobotEnhancedKeyTest
  60  */
  61 
  62 public class ModifierRobotEnhancedKeyTest extends KeyAdapter {
  63 
  64     private boolean focusGained = false;
  65     private boolean startTest = false;
  66     private ExtendedRobot robot;
  67     private Frame frame;
  68     private Canvas canvas;
  69 
  70     private volatile boolean tempPress = false;
  71 
  72     private int[] textKeys, modifierKeys, inputMasks;
  73     private boolean[] modifierStatus, textStatus;
  74 
  75     private final static int waitDelay = 5000;
  76     private Object tempLock = new Object();
  77     private Object keyLock = new Object();
  78 
  79     public static void main(String[] args) throws Exception {
  80         String os = System.getProperty("os.name").toLowerCase();
  81         if (!os.contains("windows")) {
  82             System.out.println("*** this test is for windows only because some of the tested key combinations " +
  83                                "might be caught by the os and therefore don't reach the canvas ***");
  84             return;
  85         }
  86 
  87         ModifierRobotEnhancedKeyTest test = new ModifierRobotEnhancedKeyTest();
  88         test.doTest();
  89     }
  90 
  91     public ModifierRobotEnhancedKeyTest() throws Exception {
  92         modifierKeys =  new int[4];
  93         modifierKeys[0] = KeyEvent.VK_SHIFT;
  94         modifierKeys[1] = KeyEvent.VK_CONTROL;
  95         modifierKeys[2] = KeyEvent.VK_ALT;
  96         modifierKeys[3] = KeyEvent.VK_ALT_GRAPH;
  97 
  98         inputMasks = new int[4];
  99         inputMasks[0] =  InputEvent.SHIFT_MASK;
 100         inputMasks[1] =  InputEvent.CTRL_MASK;
 101         inputMasks[2] =  InputEvent.ALT_MASK;
 102         inputMasks[3] =  InputEvent.ALT_GRAPH_MASK;
 103 
 104         modifierStatus = new boolean[modifierKeys.length];
 105 
 106         textKeys = new int[6];
 107         textKeys[0] = KeyEvent.VK_A;
 108         textKeys[1] = KeyEvent.VK_S;
 109         textKeys[2] = KeyEvent.VK_DELETE;
 110         textKeys[3] = KeyEvent.VK_HOME;
 111         textKeys[4] = KeyEvent.VK_F12;
 112         textKeys[5] = KeyEvent.VK_LEFT;
 113 
 114         textStatus = new boolean[textKeys.length];
 115 
 116         EventQueue.invokeAndWait( () -> { initializeGUI(); });
 117     }
 118 
 119     public void keyPressed(KeyEvent event) {
 120 
 121         tempPress = true;
 122         synchronized (tempLock) { tempLock.notifyAll(); }
 123 
 124         if (! startTest) {
 125             return;
 126         }
 127         for (int x = 0; x < inputMasks.length; x++) {
 128             if ((event.getModifiers() & inputMasks[x]) != 0) {
 129                 System.out.println("Modifier set: " + event.getKeyModifiersText(inputMasks[x]));
 130                 modifierStatus[x] = true;
 131             }
 132         }
 133         for (int x = 0; x < textKeys.length; x++) {
 134             if (event.getKeyCode() == textKeys[x]) {
 135                 System.out.println("Text set: " + event.getKeyText(textKeys[x]));
 136                 textStatus[x] = true;
 137             }
 138         }
 139 
 140         synchronized (keyLock) { keyLock.notifyAll(); }
 141     }
 142 
 143     private void initializeGUI() {
 144         frame = new Frame("Test frame");
 145         canvas = new Canvas();
 146         canvas.addFocusListener(new FocusAdapter() {
 147             public void focusGained(FocusEvent event) { focusGained = true; }
 148         });
 149         canvas.addKeyListener(this);
 150         frame.setLayout(new BorderLayout());
 151         frame.add(canvas);
 152         frame.setSize(200, 200);
 153         frame.setVisible(true);
 154     }
 155 
 156     public void doTest() throws Exception {
 157         robot = new ExtendedRobot();
 158 
 159         robot.mouseMove((int) frame.getLocationOnScreen().getX() + frame.getSize().width / 2,
 160                         (int) frame.getLocationOnScreen().getY() + frame.getSize().height / 2);
 161         robot.click(MouseEvent.BUTTON1_MASK);
 162         robot.waitForIdle();
 163 
 164         assertTrue(focusGained, "FAIL: Canvas gained focus!");
 165 
 166         for (int i = 0; i < modifierKeys.length; i++) {
 167             for (int j = 0; j < textKeys.length; j++) {
 168                 tempPress = false;
 169                 robot.keyPress(modifierKeys[i]);
 170                 robot.waitForIdle();
 171                 if (! tempPress) {
 172                     synchronized (tempLock) { tempLock.wait(waitDelay); }
 173                 }
 174                 assertTrue(tempPress, "FAIL: keyPressed triggered for i=" + i);
 175 
 176                 resetStatus();
 177                 startTest = true;
 178                 robot.keyPress(textKeys[j]);
 179                 robot.waitForIdle();
 180                 if (! modifierStatus[i] || ! textStatus[j]) {
 181                     synchronized (keyLock) { keyLock.wait(waitDelay); }
 182                 }
 183 
 184 
 185                 assertTrue(modifierStatus[i] && textStatus[j],
 186                         "FAIL: KeyEvent not proper!"+
 187                         "Key checked: i=" + i + "; j=" + j+
 188                         "ModifierStatus = " + modifierStatus[i]+
 189                         "TextStatus = " + textStatus[j]);
 190                 startTest = false;
 191                 robot.keyRelease(textKeys[j]);
 192                 robot.waitForIdle();
 193                 robot.keyRelease(modifierKeys[i]);
 194                 robot.waitForIdle();
 195             }
 196         }
 197 
 198         for (int i = 0; i < modifierKeys.length; i++) {
 199             for (int j = i + 1; j < modifierKeys.length; j++) {
 200                 for (int k = 0; k < textKeys.length; k++) {
 201                     tempPress = false;
 202                     robot.keyPress(modifierKeys[i]);
 203                     robot.waitForIdle();
 204                     if (! tempPress) {
 205                         synchronized (tempLock) { tempLock.wait(waitDelay); }
 206                     }
 207 
 208                     assertTrue(tempPress, "FAIL: MultiKeyTest: keyPressed triggered for i=" + i);
 209 
 210                     tempPress = false;
 211                     robot.keyPress(modifierKeys[j]);
 212                     robot.waitForIdle();
 213                     if (! tempPress) {
 214                         synchronized (tempLock) { tempLock.wait(waitDelay); }
 215                     }
 216                     assertTrue(tempPress, "FAIL: MultiKeyTest keyPressed triggered for j=" + j);
 217 
 218                     resetStatus();
 219                     startTest = true;
 220                     robot.keyPress(textKeys[k]);
 221                     robot.waitForIdle();
 222                     if (! modifierStatus[i] || ! modifierStatus[j] || ! textStatus[k]) {
 223                         synchronized (keyLock) {
 224                             keyLock.wait(waitDelay);
 225                         }
 226                     }
 227                     assertTrue(modifierStatus[i] && modifierStatus[j] && textStatus[k],
 228                             "FAIL: KeyEvent not proper!"+
 229                             "Key checked: i=" + i + "; j=" + j + "; k=" + k+
 230                             "Modifier1Status = " + modifierStatus[i]+
 231                             "Modifier2Status = " + modifierStatus[j]+
 232                             "TextStatus = " + textStatus[k]);
 233 
 234                     startTest = false;
 235                     robot.keyRelease(textKeys[k]);
 236                     robot.waitForIdle();
 237                     robot.keyRelease(modifierKeys[j]);
 238                     robot.waitForIdle();
 239                     robot.keyRelease(modifierKeys[i]);
 240                     robot.waitForIdle();
 241                 }
 242             }
 243         }
 244 
 245         frame.dispose();
 246     }
 247 
 248     private void resetStatus() {
 249         for (int i = 0; i < modifierStatus.length; i++) {
 250             modifierStatus[i] = false;
 251         }
 252         for (int i = 0; i < textStatus.length; i++) {
 253             textStatus[i] = false;
 254         }
 255     }
 256 
 257 }