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