1 /*
   2  * Copyright (c) 2005, 2019, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /*
  27   @test
  28   @bug 5025858 8144125
  29   @summary Tests that after programmatically moving or resizing a component,
  30            corresponding ComponentEvents are generated only once
  31 */
  32 
  33 import java.awt.Button;
  34 import java.awt.Component;
  35 import java.awt.Frame;
  36 import java.awt.Point;
  37 import java.awt.Robot;
  38 import java.awt.Window;
  39 import java.awt.event.ComponentAdapter;
  40 import java.awt.event.ComponentEvent;
  41 import java.awt.event.ComponentListener;
  42 
  43 /*
  44   IMPORTANT: this test can fail because some window managers may generate
  45   strange events and that would lead to the test to fail. However, on most
  46   popular platforms (windows, linux w/ KDE or GNOME, solaris w/ CDE or
  47   GNOME) it usually passes successfully.
  48 */
  49 
  50 public class MovedResizedTwiceTest
  51 {
  52     private static volatile int componentMovedCount;
  53     private static volatile int componentResizedCount;
  54 
  55     private static volatile int rightX, rightY;
  56 
  57     private static volatile boolean failed = false;
  58 
  59     private static void init()
  60     {
  61         componentMovedCount = componentResizedCount = 0;
  62 
  63         Robot robot;
  64         try {
  65             robot = new Robot();
  66         }catch(Exception ex) {
  67             ex.printStackTrace();
  68             throw new RuntimeException("Cannot create Robot: failure");
  69         }
  70 
  71         Frame f = new Frame("Frame F");
  72         f.setLayout(null);
  73         f.setBounds(100, 100, 100, 100);
  74         f.add(new Button("Button"));
  75 
  76         f.setVisible(true);
  77         robot.waitForIdle();
  78 
  79         ComponentListener cl = new ComponentAdapter()
  80         {
  81             public void componentMoved(ComponentEvent e)
  82             {
  83                 componentMovedCount++;
  84                 Component c = (Component)e.getSource();
  85                 if (!(c instanceof Window))
  86                 {
  87                     return;
  88                 }
  89                 Point p = c.getLocationOnScreen();
  90                 if ((p.x != rightX) || (p.y != rightY))
  91                 {
  92                     System.err.println("Error: wrong location on screen after COMPONENT_MOVED");
  93                     System.err.println("Location on screen is (" + p.x + ", " + p.y + ") against right location (" + rightX + ", " + rightY + ")");
  94                     failed = true;
  95                 }
  96             }
  97             public void componentResized(ComponentEvent e)
  98             {
  99                 componentResizedCount++;
 100             }
 101         };
 102 
 103         f.addComponentListener(cl);
 104 
 105         componentResizedCount = componentMovedCount = 0;
 106         rightX = 100;
 107         rightY = 100;
 108         f.setSize(200, 200);
 109         robot.waitForIdle();
 110         checkResized("setSize", f);
 111 
 112         componentResizedCount = componentMovedCount = 0;
 113         rightX = 200;
 114         rightY = 200;
 115         f.setLocation(200, 200);
 116         robot.waitForIdle();
 117         checkMoved("setLocation", f);
 118 
 119         componentResizedCount = componentMovedCount = 0;
 120         rightX = 150;
 121         rightY = 150;
 122         f.setBounds(150, 150, 100, 100);
 123         robot.waitForIdle();
 124         checkResized("setBounds", f);
 125         checkMoved("setBounds", f);
 126 
 127         Button b = new Button("B");
 128         b.setBounds(10, 10, 40, 40);
 129         f.add(b);
 130         robot.waitForIdle();
 131 
 132         b.addComponentListener(cl);
 133 
 134         componentResizedCount = componentMovedCount = 0;
 135         b.setBounds(20, 20, 50, 50);
 136         robot.waitForIdle();
 137         checkMoved("setBounds", b);
 138         checkResized("setBounds", b);
 139         f.remove(b);
 140 
 141         Component c = new Component() {};
 142         c.setBounds(10, 10, 40, 40);
 143         f.add(c);
 144         robot.waitForIdle();
 145 
 146         c.addComponentListener(cl);
 147 
 148         componentResizedCount = componentMovedCount = 0;
 149         c.setBounds(20, 20, 50, 50);
 150         robot.waitForIdle();
 151         checkMoved("setBounds", c);
 152         checkResized("setBounds", c);
 153         f.remove(c);
 154 
 155         if (failed)
 156         {
 157             MovedResizedTwiceTest.fail("Test FAILED");
 158         }
 159         else
 160         {
 161             MovedResizedTwiceTest.pass();
 162         }
 163     }
 164 
 165     private static void checkResized(String methodName, Component c)
 166     {
 167         String failMessage = null;
 168         if (componentResizedCount == 1)
 169         {
 170             return;
 171         }
 172         else if (componentResizedCount == 0)
 173         {
 174             failMessage = "Test FAILED: COMPONENT_RESIZED is not sent after call to " + methodName + "()";
 175         }
 176         else
 177         {
 178             failMessage = "Test FAILED: COMPONENT_RESIZED is sent " + componentResizedCount + " + times after call to " + methodName + "()";
 179         }
 180         System.err.println("Failed component: " + c);
 181         MovedResizedTwiceTest.fail(failMessage);
 182     }
 183 
 184     private static void checkMoved(String methodName, Component c)
 185     {
 186         String failMessage = null;
 187         if (componentMovedCount == 1)
 188         {
 189             return;
 190         }
 191         if (componentMovedCount == 0)
 192         {
 193             failMessage = "Test FAILED: COMPONENT_MOVED is not sent after call to " + methodName + "()";
 194         }
 195         else
 196         {
 197             failMessage = "Test FAILED: COMPONENT_MOVED is sent " + componentMovedCount + " times after call to " + methodName + "()";
 198         }
 199         System.err.println("Failed component: " + c);
 200         MovedResizedTwiceTest.fail(failMessage);
 201     }
 202 
 203     private static boolean theTestPassed = false;
 204     private static boolean testGeneratedInterrupt = false;
 205     private static String failureMessage = "";
 206 
 207     private static Thread mainThread = null;
 208 
 209     private static int sleepTime = 300000;
 210 
 211     public static void main( String args[] ) throws InterruptedException
 212     {
 213         mainThread = Thread.currentThread();
 214         try
 215         {
 216             init();
 217         }
 218         catch (TestPassedException e)
 219         {
 220             return;
 221         }
 222 
 223         try
 224         {
 225             Thread.sleep(sleepTime);
 226             throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
 227         }
 228         catch (InterruptedException e)
 229         {
 230             if (!testGeneratedInterrupt)
 231             {
 232                 throw e;
 233             }
 234 
 235             testGeneratedInterrupt = false;
 236 
 237             if (!theTestPassed)
 238             {
 239                 throw new RuntimeException( failureMessage );
 240             }
 241         }
 242     }
 243 
 244     public static synchronized void setTimeoutTo(int seconds)
 245     {
 246         sleepTime = seconds * 1000;
 247     }
 248 
 249     public static synchronized void pass()
 250     {
 251         if (mainThread == Thread.currentThread())
 252         {
 253             theTestPassed = true;
 254             throw new TestPassedException();
 255         }
 256         theTestPassed = true;
 257         testGeneratedInterrupt = true;
 258         mainThread.interrupt();
 259     }
 260 
 261     public static synchronized void fail()
 262     {
 263         fail("it just plain failed! :-)");
 264     }
 265 
 266     public static synchronized void fail(String whyFailed)
 267     {
 268         if (mainThread == Thread.currentThread())
 269         {
 270             throw new RuntimeException(whyFailed);
 271         }
 272         theTestPassed = false;
 273         testGeneratedInterrupt = true;
 274         failureMessage = whyFailed;
 275         mainThread.interrupt();
 276     }
 277 }
 278 
 279 class TestPassedException extends RuntimeException
 280 {
 281 }