1 /*
   2  * Copyright (c) 2007, 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 import java.awt.*;
  25 import java.awt.event.*;
  26 import java.awt.image.BufferedImage;
  27 
  28 /*
  29  * @test
  30  * @summary Check for MouseEvents with all mouse buttons
  31  * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
  32  * @library ../../../../lib/testlibrary ../
  33  * @build ExtendedRobot SystemTrayIconHelper
  34  * @run main ModalityTest
  35  */
  36 public class ModalityTest {
  37 
  38     TrayIcon icon;
  39     ExtendedRobot robot;
  40     Dialog d;
  41 
  42     boolean actionPerformed = false;
  43 
  44     private boolean dialogVisible = false;
  45     private Object dialogLock = new Object();
  46 
  47     Object actionLock = new Object();
  48     Object pressLock = new Object();
  49     Object releaseLock = new Object();
  50     Object clickLock = new Object();
  51     Object moveLock = new Object();
  52     static final int clickDelay = 50;
  53 
  54     boolean mousePressed = false;
  55     boolean mouseReleased = false;
  56     boolean mouseClicked = false;
  57     boolean mouseMoved = false;
  58 
  59     int[] buttonTypes = {
  60         InputEvent.BUTTON1_MASK,
  61         InputEvent.BUTTON2_MASK,
  62         InputEvent.BUTTON3_MASK
  63     };
  64 
  65     String[] buttonNames = {
  66         "BUTTON1",
  67         "BUTTON2",
  68         "BUTTON3"
  69     };
  70 
  71     public static void main(String[] args) throws Exception {
  72         if (! SystemTray.isSupported()) {
  73             System.out.println("SystemTray not supported on the platform under test. " +
  74                                "Marking the test passed");
  75         } else {
  76             if (System.getProperty("os.name").toLowerCase().startsWith("win"))
  77                 System.err.println("Test can fail if the icon hides to a tray icons pool " +
  78                         "in Windows 7, which is behavior by default.\n" +
  79                         "Set \"Right mouse click\" -> \"Customize notification icons\" -> " +
  80                         "\"Always show all icons and notifications on the taskbar\" true " +
  81                         "to avoid this problem. Or change behavior only for Java SE tray " +
  82                         "icon and rerun test.");
  83 
  84             new ModalityTest().doTest();
  85         }
  86     }
  87 
  88     public ModalityTest() throws Exception {
  89         robot = new ExtendedRobot();
  90         EventQueue.invokeLater(this::initializeGUI);
  91     }
  92 
  93     void initializeGUI() {
  94         SystemTray tray = SystemTray.getSystemTray();
  95         icon = new TrayIcon(new BufferedImage(20, 20, BufferedImage.TYPE_INT_RGB), "Sample Icon");
  96         icon.addActionListener(event -> {
  97             actionPerformed = true;
  98             synchronized (actionLock) {
  99                 try {
 100                     actionLock.notifyAll();
 101                 } catch (Exception e) {
 102                 }
 103             }
 104         });
 105         icon.addMouseListener(new MouseAdapter() {
 106             public void mousePressed(MouseEvent event) {
 107                 mousePressed = true;
 108                 Point p = event.getPoint();
 109                 if (p.x != event.getX() || p.y != event.getY())
 110                     throw new RuntimeException("FAIL: MouseEvent.getPoint() did " +
 111                             "not return the same value as getX/getY " +
 112                             "for mousePressed");
 113 
 114                 if (! icon.equals(event.getSource()))
 115                     throw new RuntimeException("FAIL: mousePressed: MouseEvent.getSource " +
 116                             "did not return TrayIcon object");
 117 
 118                 synchronized (pressLock) {
 119                     try {
 120                         pressLock.notifyAll();
 121                     } catch (Exception e) {
 122                     }
 123                 }
 124             }
 125 
 126             public void mouseReleased(MouseEvent event) {
 127                 mouseReleased = true;
 128                 Point p = event.getPoint();
 129                 if (p.x != event.getX() || p.y != event.getY())
 130                     throw new RuntimeException("FAIL: MouseEvent.getPoint() did " +
 131                             "not return the same value as getX/getY " +
 132                             "for mouseReleased");
 133 
 134                 if (! icon.equals(event.getSource()))
 135                     throw new RuntimeException("FAIL: mouseReleased: MouseEvent.getSource " +
 136                             "did not return TrayIcon object");
 137 
 138                 synchronized (releaseLock) {
 139                     try {
 140                         releaseLock.notifyAll();
 141                     } catch (Exception e) {
 142                     }
 143                 }
 144             }
 145 
 146             public void mouseClicked(MouseEvent event) {
 147                 mouseClicked = true;
 148                 Point p = event.getPoint();
 149                 if (p.x != event.getX() || p.y != event.getY())
 150                     throw new RuntimeException("FAIL: MouseEvent.getPoint() did " +
 151                             "not return the same value as getX/getY " +
 152                             "for mouseClicked");
 153 
 154                 if (! icon.equals(event.getSource()))
 155                     throw new RuntimeException("FAIL: mouseClicked: MouseEvent.getSource " +
 156                             "did not return TrayIcon object");
 157 
 158                 synchronized (clickLock) {
 159                     try {
 160                         clickLock.notifyAll();
 161                     } catch (Exception e) {
 162                     }
 163                 }
 164             }
 165         });
 166 
 167         icon.addMouseMotionListener(new MouseMotionAdapter() {
 168             public void mouseMoved(MouseEvent event) {
 169                 mouseMoved = true;
 170                 Point p = event.getPoint();
 171                 if (p.x != event.getX() || p.y != event.getY())
 172                     throw new RuntimeException("FAIL: MouseEvent.getPoint() did " +
 173                             "not return the same value as getX/getY " +
 174                             "for mouseMoved");
 175 
 176                 if (!icon.equals(event.getSource()))
 177                     throw new RuntimeException("FAIL: mouseMoved: MouseEvent.getSource " +
 178                             "did not return TrayIcon object");
 179 
 180                 synchronized (moveLock) {
 181                     try {
 182                         moveLock.notifyAll();
 183                     } catch (Exception e) {
 184                     }
 185                 }
 186             }
 187         });
 188 
 189         try {
 190             tray.add(icon);
 191         } catch (AWTException e) {
 192             throw new RuntimeException(e);
 193         }
 194 
 195         d = new Dialog((Frame) null, "Modal Dialog");
 196         d.setLocation(200, 200);
 197         d.setSize(100, 100);
 198         d.setModalityType(Dialog.ModalityType.TOOLKIT_MODAL);
 199 
 200         dialogVisible = true;
 201         synchronized (dialogLock) {
 202             try {
 203                 dialogLock.notifyAll();
 204             } catch (Exception e) {
 205             }
 206         }
 207 
 208         d.setVisible(true);
 209     }
 210 
 211     void doTest() throws Exception {
 212 
 213         if (! dialogVisible) {
 214             synchronized (dialogLock) {
 215                 try {
 216                     dialogLock.wait(3000);
 217                 } catch (Exception e) {
 218                 }
 219             }
 220         }
 221 
 222         if (! dialogVisible)
 223             throw new RuntimeException("ERROR: TIMEOUT: The thread in EDT not yet complete");
 224 
 225         Point iconPosition = SystemTrayIconHelper.getTrayIconLocation(icon);
 226         if (iconPosition == null)
 227             throw new RuntimeException("Unable to find the icon location!");
 228 
 229         if (! d.isVisible())
 230             throw new RuntimeException("FAIL: The modal dialog is not yet visible");
 231 
 232         robot.mouseMove(iconPosition.x, iconPosition.y);
 233         robot.waitForIdle(2000);
 234 
 235         SystemTrayIconHelper.doubleClick(robot);
 236 
 237         if (! actionPerformed) {
 238             synchronized (actionLock) {
 239                 try {
 240                     actionLock.wait(3000);
 241                 } catch (Exception e) {
 242                 }
 243             }
 244         }
 245         if (! actionPerformed)
 246             throw new RuntimeException("FAIL: ActionEvent not triggered when TrayIcon is double clicked");
 247 
 248         for (int i = 0; i < buttonTypes.length; i++) {
 249             mousePressed = false;
 250             robot.mousePress(buttonTypes[i]);
 251 
 252             if (! mousePressed) {
 253                 synchronized (pressLock) {
 254                     try {
 255                         pressLock.wait(3000);
 256                     } catch (Exception e) {
 257                     }
 258                 }
 259             }
 260             if (! mousePressed)
 261                 if (! SystemTrayIconHelper.skip(buttonTypes[i]) )
 262                     throw new RuntimeException("FAIL: mousePressed not triggered when " +
 263                             buttonNames[i] + " pressed");
 264 
 265             mouseReleased = false;
 266             mouseClicked = false;
 267             robot.mouseRelease(buttonTypes[i]);
 268 
 269             if (! mouseReleased) {
 270                 synchronized (releaseLock) {
 271                     try {
 272                         releaseLock.wait(3000);
 273                     } catch (Exception e) {
 274                     }
 275                 }
 276             }
 277             if (! mouseReleased)
 278                 throw new RuntimeException("FAIL: mouseReleased not triggered when " +
 279                         buttonNames[i] + " released");
 280 
 281             if (! mouseClicked) {
 282                 synchronized (clickLock) {
 283                     try {
 284                         clickLock.wait(3000);
 285                     } catch (Exception e) {
 286                     }
 287                 }
 288             }
 289             if (! mouseClicked)
 290                 throw new RuntimeException("FAIL: mouseClicked not triggered when " +
 291                         buttonNames[i] + " pressed & released");
 292         }
 293 
 294         mouseMoved = false;
 295         robot.mouseMove(iconPosition.x, iconPosition.y);
 296         robot.glide(iconPosition.x + 100, iconPosition.y);
 297 
 298         if (! mouseMoved)
 299             if (! SystemTrayIconHelper.skip(0) )
 300                 throw new RuntimeException("FAIL: mouseMoved not triggered even when mouse moved over the icon");
 301     }
 302 }