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 %I% %E%
  26   @key headful
  27   @bug 6315717
  28   @summary verifies that modifiers are correct for extra buttons
  29   @author Andrei Dmitriev : area=awt.mouse
  30   @library ../../../../lib/testlibrary
  31   @build jdk.testlibrary.OSInfo
  32   @run main MouseModifiersUnitTest_Extra
  33  */
  34 
  35 import jdk.testlibrary.OSInfo;
  36 
  37 import java.awt.*;
  38 import java.awt.event.*;
  39 import java.util.Arrays;
  40 import java.util.HashMap;
  41 import java.util.StringTokenizer;
  42 import java.util.Vector;
  43 
  44 // will process extra buttons only
  45 // asking parameters from CMD: manual/automatic, modifier to test
  46 
  47 public class MouseModifiersUnitTest_Extra extends Frame {
  48     static final int NONE = 0;
  49     static final int SHIFT = 1;
  50     static final int CTRL = 2;
  51     static final int ALT = 3;
  52     static CheckingModifierAdapterExtra adapterTest1;
  53     static CheckingModifierAdapterExtra adapterTest2;
  54     static CheckingModifierAdapterExtra adapterTest3;
  55     static CheckingModifierAdapterExtra adapterTest4;
  56 
  57     static boolean debug = true; //dump all errors (debug) or throw first(under jtreg) exception
  58     static boolean autorun = false; //use robot or manual run
  59     static int testModifier = NONE;
  60 
  61     static int [] mouseButtonDownMasks;
  62 
  63     //an arrays representing a modifiersEx of extra mouse buttons while using ALT/CTRL/SHIFT or none of them
  64     static int [] modifiersExStandard;
  65     static int [] modifiersExStandardSHIFT;
  66     static int [] modifiersExStandardCTRL;
  67     static int [] modifiersExStandardALT;
  68 
  69     private final static String SHIFT_MODIFIER = OSInfo.getOSType().equals(OSInfo.OSType.MACOSX) ?
  70                                                 "\u21e7" : "Shift";
  71 
  72     private final static String ALT_MODIFIER = OSInfo.getOSType().equals(OSInfo.OSType.MACOSX) ?
  73                                                 "\u2325" : "Alt";
  74 
  75 
  76     private final static String CTRL_MODIFIER = OSInfo.getOSType().equals(OSInfo.OSType.MACOSX) ?
  77                                                 "\u2303" : "Ctrl";
  78 
  79 
  80     // BUTTON1, 2, 3 press-release.
  81     final static int  modifiersStandard = 0; //InputEvent.BUTTON_DOWN_MASK;
  82 
  83     public static void checkPressedModifiersTest(int testModifier, MouseEvent event){
  84         int [] curStandardExModifiers = getStandardExArray(testModifier);
  85         int button = event.getButton();
  86         int modifiers = event.getModifiers();
  87         int modifiersEx = event.getModifiersEx();
  88         int index = (button - 4)*3;
  89         dumpValues(button, modifiers, modifiersStandard, modifiersEx, curStandardExModifiers[index]);
  90         if (modifiers != modifiersStandard){
  91             MessageLogger.reportError("Test failed :  Pressed. modifiers != modifiersStandard");
  92         }
  93 
  94         if (modifiersEx != curStandardExModifiers[index]){
  95 //            System.out.println(">>>>>>>>>>>>>>> Pressed. modifiersEx "+modifiersEx +" : "+!= curStandardExModifiers");
  96             MessageLogger.reportError("Test failed :  Pressed. modifiersEx != curStandardExModifiers. Got: "
  97                     + modifiersEx + " , Expected: " + curStandardExModifiers[index]);
  98         }
  99 
 100      //check event.paramString() output
 101         HashMap <String, String> paramStringElements = tokenizeParamString(event.paramString());
 102         System.out.println(event.paramString());
 103         checkButton(paramStringElements, button);
 104         checkModifiers(testModifier, paramStringElements, button);
 105         checkExtModifiersOnPress(testModifier, paramStringElements, button);
 106     }
 107 
 108     public static void checkExtModifiersOnReleaseClick(int testModifier, HashMap<String, String> h, int button){
 109         String ethalon = "";
 110         switch (testModifier){
 111             case SHIFT:{
 112                 ethalon = SHIFT_MODIFIER;
 113                 break;
 114             }
 115             case ALT:{
 116                 ethalon = ALT_MODIFIER;
 117                 break;
 118             }
 119             case CTRL:{
 120                 ethalon = CTRL_MODIFIER;
 121                 break;
 122             }
 123         }
 124 
 125         if (h.get("extModifiers") == null){
 126             h.put("extModifiers", "");
 127         }
 128 
 129         if (!ethalon.equals(h.get("extModifiers"))) {
 130             MessageLogger.reportError("Test failed :  Released/Clicked. extModifiers = "
 131                     + h.get("extModifiers") + " instead of : " + ethalon);
 132         }
 133     }
 134 
 135     public static void checkExtModifiersOnPress(int testModifier, HashMap<String, String> h, int button){
 136         String ethalon = "";
 137         switch (testModifier){
 138             case SHIFT:{
 139                 ethalon = SHIFT_MODIFIER + "+";
 140                 break;
 141             }
 142             case ALT:{
 143                 ethalon = ALT_MODIFIER + "+";
 144                 break;
 145             }
 146             case CTRL:{
 147                 ethalon = CTRL_MODIFIER + "+";
 148                 break;
 149             }
 150         }
 151         ethalon = ethalon + "Button" +button;
 152 
 153         if (!h.get("extModifiers").equals(ethalon)) {
 154             MessageLogger.reportError("Test failed :  Pressed. extModifiers = " +h.get("extModifiers")+" instead of : "
 155                     + ethalon);
 156         }
 157     }
 158 
 159     public static void checkModifiers(int testModifier, HashMap<String, String> h, int button){
 160         // none of modifiers for extra button should be null
 161         if (h.get("modifiers") != null) {
 162             MessageLogger.reportError("Test failed : modifiers != null");
 163         }
 164     }
 165 
 166     public static void checkButton(HashMap<String, String> h, int button){
 167         if (h.get("button") == null) {
 168             MessageLogger.reportError("Test failed :  checkButton(). button is absent in paramString()");
 169         }
 170         if (Integer.parseInt(h.get("button")) != button) {
 171             MessageLogger.reportError("Test failed :  checkButton. button in paramString() doesn't equal to button being pressed.");
 172         }
 173     }
 174     public static HashMap<String, String> tokenizeParamString(String param){
 175         HashMap <String, String> params = new HashMap<>();
 176         StringTokenizer st = new StringTokenizer(param, ",=");
 177         while (st.hasMoreTokens()){
 178             String tmp = st.nextToken();
 179 //            System.out.println("PARSER : "+tmp);
 180             if (tmp.equals("button") ||
 181                     tmp.equals("modifiers") ||
 182                     tmp.equals("extModifiers")) {
 183                 params.put(tmp, st.nextToken());
 184             }
 185         }
 186         return params;
 187     }
 188 
 189     public static Vector<String> tokenizeModifiers(String modifierList){
 190         Vector<String> modifiers = new Vector<>();
 191         StringTokenizer st = new StringTokenizer(modifierList, "+");
 192         while (st.hasMoreTokens()){
 193             String tmp = st.nextToken();
 194             modifiers.addElement(tmp);
 195             System.out.println("MODIFIER PARSER : "+tmp);
 196         }
 197         return modifiers;
 198     }
 199 
 200     public static void checkReleasedModifiersTest(int testModifier, MouseEvent event){
 201         int [] curStandardExModifiers = getStandardExArray(testModifier);
 202         int button = event.getButton();
 203         int modifiers = event.getModifiers();
 204         int modifiersEx = event.getModifiersEx();
 205         int index = (button - 4)*3 + 1;
 206         dumpValues(button, modifiers, modifiersStandard, modifiersEx, curStandardExModifiers[index]);
 207         if (modifiers != modifiersStandard){
 208             MessageLogger.reportError("Test failed :  Released. modifiers != modifiersStandard");
 209         }
 210 
 211         if (modifiersEx != curStandardExModifiers[index]){
 212             MessageLogger.reportError("Test failed :  Released. modifiersEx != curStandardExModifiers. Got: "
 213                     + modifiersEx + " , Expected: " + curStandardExModifiers[index]);
 214         }
 215 
 216      //check event.paramString() output
 217         HashMap <String, String> paramStringElements = tokenizeParamString(event.paramString());
 218         checkButton(paramStringElements, button);
 219         checkModifiers(testModifier, paramStringElements, button);
 220         System.out.println("paramStringElements = "+paramStringElements);
 221         checkExtModifiersOnReleaseClick(testModifier, paramStringElements, button);
 222     }
 223 
 224     public static void checkClickedModifiersTest(int testModifier, MouseEvent event){
 225         int [] curStandardExModifiers = getStandardExArray(testModifier);
 226         int button = event.getButton();
 227         int modifiers = event.getModifiers();
 228         int modifiersEx = event.getModifiersEx();
 229         int index = (button - 4)*3 + 2;
 230         dumpValues(button, modifiers, modifiersStandard, modifiersEx, curStandardExModifiers[index]);
 231         if (modifiers != modifiersStandard){
 232             MessageLogger.reportError("Test failed :  Clicked. modifiers != modifiersStandard");
 233         }
 234 
 235         if (modifiersEx != curStandardExModifiers[index]){
 236             MessageLogger.reportError("Test failed :  Clicked. modifiersEx != curStandardExModifiers. Got: "
 237                     + modifiersEx + " , Expected: " + curStandardExModifiers[index]);
 238         }
 239 
 240      //check event.paramString() output
 241         HashMap <String, String> paramStringElements = tokenizeParamString(event.paramString());
 242         checkButton(paramStringElements, button);
 243         checkModifiers(testModifier, paramStringElements, button);
 244         checkExtModifiersOnReleaseClick(testModifier, paramStringElements, button);
 245     }
 246 
 247     private static int[] getStandardExArray(int testModifier) {
 248         int [] curStandardExModifiers;
 249         switch (testModifier){
 250             case SHIFT:
 251                 curStandardExModifiers = modifiersExStandardSHIFT;
 252                 break;
 253             case CTRL:
 254                 curStandardExModifiers = modifiersExStandardCTRL;
 255                 break;
 256             case ALT:
 257                 curStandardExModifiers = modifiersExStandardALT;
 258                 break;
 259             default: //NONE by default
 260                 curStandardExModifiers = modifiersExStandard;
 261         }
 262         return curStandardExModifiers;
 263     }
 264 
 265     static Robot robot;
 266     public void init() {
 267         this.setLayout(new BorderLayout());
 268         try {
 269             robot  = new Robot();
 270             robot.setAutoDelay(100);
 271             robot.setAutoWaitForIdle(true);
 272         } catch (Exception e) {
 273             MessageLogger.reportError("Test failed. "+e);
 274         }
 275     }//End  init()
 276 
 277     public void start() {
 278         //Get things going.  Request focus, set size, et cetera
 279         setSize(200,200);
 280         setVisible(true);
 281         validate();
 282         if (autorun) {
 283             testNONE();
 284             testSHIFT();
 285             testCTRL();
 286             testALT();
 287         } else {
 288             switch (testModifier){
 289                 case SHIFT:
 290                     this.addMouseListener(adapterTest2);
 291                     break;
 292                 case CTRL:
 293                     this.addMouseListener(adapterTest3);
 294                     break;
 295                 case ALT:
 296                     this.addMouseListener(adapterTest4);
 297                     break;
 298                 default:  //NONE by default
 299                     this.addMouseListener(adapterTest1);
 300             }
 301         }
 302     }// start()
 303 
 304     //000000000000000000000000000000000000000000000000000000000000000
 305     public void testNONE(){
 306         this.addMouseListener(adapterTest1);
 307         robot.delay(1000);
 308         robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2);
 309         for (int i = 3; i< mouseButtonDownMasks.length; i++){
 310             System.out.println("testNONE() => " + mouseButtonDownMasks[i]);
 311             robot.mousePress(mouseButtonDownMasks[i]);
 312             robot.mouseRelease(mouseButtonDownMasks[i]);
 313         }
 314         robot.delay(1000);
 315         this.removeMouseListener(adapterTest1);
 316     }
 317 
 318     public void testSHIFT(){
 319         this.addMouseListener(adapterTest2);
 320         robot.delay(1000);
 321         robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2);
 322         for (int i = 3; i< mouseButtonDownMasks.length; i++){
 323             robot.keyPress(KeyEvent.VK_SHIFT);
 324             System.out.println("testSHIFT() => " + mouseButtonDownMasks[i]);
 325             robot.mousePress(mouseButtonDownMasks[i]);
 326             robot.mouseRelease(mouseButtonDownMasks[i]);
 327             robot.keyRelease(KeyEvent.VK_SHIFT);
 328         }
 329         robot.delay(1000);
 330         this.removeMouseListener(adapterTest2);
 331     }
 332 
 333     public void testCTRL(){
 334         this.addMouseListener(adapterTest3);
 335         robot.delay(1000);
 336         robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2);
 337         for (int i = 3; i< mouseButtonDownMasks.length; i++){
 338             robot.keyPress(KeyEvent.VK_CONTROL);
 339             System.out.println("testCTRL() => " + mouseButtonDownMasks[i]);
 340             robot.mousePress(mouseButtonDownMasks[i]);
 341             robot.mouseRelease(mouseButtonDownMasks[i]);
 342             robot.keyRelease(KeyEvent.VK_CONTROL);
 343         }
 344         robot.delay(1000);
 345         this.removeMouseListener(adapterTest3);
 346     }
 347 
 348     public void testALT(){
 349         this.addMouseListener(adapterTest4);
 350         robot.delay(1000);
 351         robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2);
 352         for (int i = 3; i< mouseButtonDownMasks.length; i++){
 353             robot.keyPress(KeyEvent.VK_ALT);
 354             System.out.println("testALT() => " + mouseButtonDownMasks[i]);
 355             robot.mousePress(mouseButtonDownMasks[i]);
 356             robot.mouseRelease(mouseButtonDownMasks[i]);
 357             robot.keyRelease(KeyEvent.VK_ALT);
 358         }
 359         robot.delay(1000);
 360         this.removeMouseListener(adapterTest4);
 361     }
 362 
 363     //**************************************************************************************************
 364     public static void dumpValues(int button, int modifiers, int modifiersStandard, int modifiersEx, int modifiersExStandard){
 365         System.out.println("Button = "+button + "Modifiers = "+ modifiers + "standard = "+ modifiersStandard);
 366         System.out.println("Button = "+button + "ModifiersEx = "+ modifiersEx + "standardEx = "+ modifiersExStandard);
 367     }
 368 
 369     public static void initParams(String []s){
 370         if (s.length != 3){
 371             autorun = true;
 372             debug = false;
 373             testModifier = NONE;
 374         } else {
 375             autorun = Boolean.valueOf(s[0]);
 376             debug = Boolean.valueOf(s[1]);
 377 
 378             if (s[2].equals("NONE")){
 379                 testModifier = NONE;
 380             }
 381             if (s[2].equals("SHIFT")){
 382                 testModifier = SHIFT;
 383             }
 384             if (s[2].equals("CTRL")){
 385                 testModifier = CTRL;
 386             }
 387             if (s[2].equals("ALT")){
 388                 testModifier = ALT;
 389             }
 390         }
 391         MessageLogger.setDebug(debug);
 392         System.out.println("Autorun : " +autorun);
 393         System.out.println("Debug mode : " +debug);
 394         System.out.println("Modifier to verify : " + testModifier);
 395     }
 396 
 397     public static void initAdapters(){
 398         adapterTest1 = new CheckingModifierAdapterExtra(NONE);
 399         adapterTest2 = new CheckingModifierAdapterExtra(SHIFT);
 400         adapterTest3 = new CheckingModifierAdapterExtra(CTRL);
 401         adapterTest4 = new CheckingModifierAdapterExtra(ALT);
 402     }
 403 
 404     public static void initVars(){
 405         //Init the array of the mouse button masks. It will be used for generating mouse events.
 406         mouseButtonDownMasks = new int [MouseInfo.getNumberOfButtons()];
 407         for (int i = 0; i < mouseButtonDownMasks.length; i++){
 408             mouseButtonDownMasks[i] = InputEvent.getMaskForButton(i+1);
 409             System.out.println("MouseArray [i] == "+mouseButtonDownMasks[i]);
 410         }
 411 
 412         // So we need to get the number of extra buttons on the mouse:  "MouseInfo.getNumberOfButtons() - 3"
 413         // and multyply on 3 because each button will generate three events : PRESS, RELEASE and CLICK.
 414         int [] tmp = new int [(MouseInfo.getNumberOfButtons()-3)*3];
 415 
 416         //Fill array of expected results for the case when mouse buttons are only used (no-modifier keys)
 417         Arrays.fill(tmp, 0);
 418         for (int i = 0, j = 3; i < tmp.length; i = i + 3, j++){
 419             tmp[i] = mouseButtonDownMasks[j];
 420         }
 421         modifiersExStandard = Arrays.copyOf(tmp, tmp.length);
 422 
 423         //Fill array of expected results for the case when mouse buttons are only used with SHIFT modifier key
 424         Arrays.fill(tmp, InputEvent.SHIFT_DOWN_MASK);
 425         for (int i = 0, j = 3; i < tmp.length; i = i + 3, j++){
 426             System.out.println("modifiersExStandardSHIFT FILLING : " + tmp[i] + " + " + mouseButtonDownMasks[j]);
 427             tmp[i] = tmp[i] | mouseButtonDownMasks[j];
 428         }
 429         modifiersExStandardSHIFT = Arrays.copyOf(tmp, tmp.length);
 430 
 431         //Fill array of expected results for the case when mouse buttons are only used with CTRL modifier key
 432         Arrays.fill(tmp, InputEvent.CTRL_DOWN_MASK);
 433         for (int i = 0, j = 3; i < tmp.length; i = i + 3, j++){
 434             System.out.println("modifiersExStandardCTRL FILLING : " + tmp[i] + " + " + mouseButtonDownMasks[j]);
 435             tmp[i] = tmp[i] | mouseButtonDownMasks[j];
 436         }
 437         modifiersExStandardCTRL = Arrays.copyOf(tmp, tmp.length);
 438 
 439         //Fill array of expected results for the case when mouse buttons are only used with ALT modifier key
 440         Arrays.fill(tmp, InputEvent.ALT_DOWN_MASK);
 441         for (int i = 0, j = 3; i < tmp.length; i = i + 3, j++){
 442             System.out.println("modifiersExStandardALT FILLING : " + tmp[i] + " + " + mouseButtonDownMasks[j]);
 443             tmp[i] = tmp[i] | mouseButtonDownMasks[j];
 444         }
 445         modifiersExStandardALT = Arrays.copyOf(tmp, tmp.length);
 446     }
 447 
 448     public static void main(String []s){
 449         if (MouseInfo.getNumberOfButtons() < 4){
 450             System.out.println("There are less than 4 buttons on the mouse. The test may not be accomplished. Skipping.");
 451             return;
 452         }
 453         initVars();
 454         MouseModifiersUnitTest_Extra frame = new MouseModifiersUnitTest_Extra();
 455         frame.initParams(s);
 456         frame.init();
 457         initAdapters();
 458         frame.start();
 459     }
 460 
 461 }// class
 462 
 463 /* A class that invoke appropriate verification
 464  * routine with current modifier.
 465  */
 466 class CheckingModifierAdapterExtra extends MouseAdapter{
 467     int modifier;
 468     public CheckingModifierAdapterExtra(int modifier){
 469         this.modifier = modifier;
 470     }
 471 
 472     public void mousePressed(MouseEvent e) {
 473         System.out.println("PRESSED "+e);
 474         if (e.getButton() <= MouseEvent.BUTTON3) {
 475             System.out.println("Standard button affected. Skip.");
 476         } else {
 477             MouseModifiersUnitTest_Extra.checkPressedModifiersTest(modifier, e);
 478         }
 479     }
 480     public void mouseReleased(MouseEvent e) {
 481         System.out.println("RELEASED "+e);
 482         if (e.getButton() <= MouseEvent.BUTTON3) {
 483             System.out.println("Standard button affected. Skip.");
 484         } else {
 485             MouseModifiersUnitTest_Extra.checkReleasedModifiersTest(modifier, e);
 486         }
 487     }
 488     public void mouseClicked(MouseEvent e) {
 489         System.out.println("CLICKED "+e);
 490         if (e.getButton() <= MouseEvent.BUTTON3) {
 491             System.out.println("Standard button affected. Skip.");
 492         } else {
 493             MouseModifiersUnitTest_Extra.checkClickedModifiersTest(modifier, e);
 494         }
 495     }
 496 }
 497 //Utility class that could report a message depending on current purpose of the test run
 498 class MessageLogger{
 499     private static boolean debug;
 500 
 501     public static void setDebug(boolean d){
 502         debug = d;
 503         log("Switch to "+ ((debug)?"debug":"trial") +" mode");
 504     }
 505 
 506     public static void log(String message){
 507         System.out.println(message);
 508     }
 509 
 510     public static void reportError(String message){
 511         if (debug){
 512             System.out.println(message);
 513         } else {
 514             throw new RuntimeException(message);
 515         }
 516     }
 517 }