1 /*
   2  * Copyright (c) 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
  26   @key headful
  27   @bug 5097801 8163270
  28   @summary Tests that no mouse events are sent to component if robot is
  29            moving mouse on another screen, Xinerama
  30   @run main SpuriousMouseEvents
  31  */
  32 import java.awt.GraphicsEnvironment;
  33 import java.awt.GraphicsDevice;
  34 import java.awt.Robot;
  35 import java.awt.GraphicsConfiguration;
  36 import java.awt.Frame;
  37 import java.awt.event.MouseMotionAdapter;
  38 import java.awt.event.MouseEvent;
  39 
  40 public class SpuriousMouseEvents {
  41 
  42     private static volatile boolean testPassed = true;
  43     private static boolean theTestPassed = false;
  44     private static boolean testGeneratedInterrupt = false;
  45     private static String failureMessage = "";
  46     private static Thread mainThread = null;
  47     private static int sleepTime = 60000;
  48 
  49     private static void init() throws Exception {
  50         GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
  51         GraphicsDevice[] gds = ge.getScreenDevices();
  52         if (gds.length < 2) {
  53             pass();
  54             return;
  55         }
  56 
  57         Robot r = null;
  58         try {
  59             r = new Robot();
  60         } catch (Exception z) {
  61             z.printStackTrace(System.err);
  62             fail("Couldn't create AWT robot");
  63             return;
  64         }
  65 
  66         for (int i = 1; i >= 0; i--) {
  67             testPassed = true;
  68 
  69             GraphicsDevice gd = gds[i];
  70             GraphicsDevice gdo = gds[1 - i];
  71             GraphicsConfiguration gc = gd.getDefaultConfiguration();
  72             GraphicsConfiguration gco = gdo.getDefaultConfiguration();
  73             Frame f = new Frame("Frame", gc);
  74             f.setBounds(gc.getBounds().x + 100, gc.getBounds().y + 100, 200, 200);
  75             f.addMouseMotionListener(new MouseMotionAdapter() {
  76                 public void mouseMoved(MouseEvent me) {
  77                     testPassed = false;
  78                 }
  79             });
  80             f.setVisible(true);
  81 
  82             r = new Robot(gdo);
  83             int x = (int) gco.getBounds().x;
  84             for (int j = x; j < x + 400; j += 10) {
  85                 r.mouseMove(j, 200);
  86                 r.delay(10);
  87             }
  88             r.delay(1000);
  89 
  90             f.setVisible(false);
  91 
  92             if (!testPassed) {
  93                 break;
  94             }
  95         }
  96 
  97         if (testPassed) {
  98             pass();
  99         } else {
 100             fail("Wrong mouse events are sent");
 101         }
 102     }
 103 
 104     public static void main(String args[])
 105             throws InterruptedException {
 106         mainThread = Thread.currentThread();
 107         try {
 108             init();
 109         } catch (TestPassedException e) {
 110             return;
 111         } catch (Exception e) {
 112             throw new RuntimeException(e);
 113         }
 114 
 115         try {
 116             Thread.sleep(sleepTime);
 117             throw new RuntimeException("Timed out after " + sleepTime / 1000
 118                     + " seconds");
 119         } catch (InterruptedException e) {
 120             if (!testGeneratedInterrupt) {
 121                 throw e;
 122             }
 123 
 124             testGeneratedInterrupt = false;
 125 
 126             if (theTestPassed == false) {
 127                 throw new RuntimeException(failureMessage);
 128             }
 129         }
 130     }
 131 
 132     public static synchronized void setTimeoutTo(int seconds) {
 133         sleepTime = seconds * 1000;
 134     }
 135 
 136     public static synchronized void pass() {
 137         if (mainThread == Thread.currentThread()) {
 138             theTestPassed = true;
 139             throw new TestPassedException();
 140         }
 141         theTestPassed = true;
 142         testGeneratedInterrupt = true;
 143         mainThread.interrupt();
 144     }
 145 
 146     public static synchronized void fail() {
 147         fail("it just plain failed)");
 148     }
 149 
 150     public static synchronized void fail(String whyFailed) {
 151         if (mainThread == Thread.currentThread()) {
 152             throw new RuntimeException(whyFailed);
 153         }
 154         theTestPassed = false;
 155         testGeneratedInterrupt = true;
 156         failureMessage = whyFailed;
 157         mainThread.interrupt();
 158     }
 159 }
 160 
 161 class TestPassedException extends RuntimeException {
 162 }