/* * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* @test @key headful @bug 7154177 8285094 @summary An invisible owner frame should never become visible @run main InvisibleOwner */ import java.awt.Color; import java.awt.EventQueue; import java.awt.Frame; import java.awt.Rectangle; import java.awt.Robot; import java.awt.Toolkit; import java.awt.Window; import java.awt.event.InputEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class InvisibleOwner { private static volatile boolean invisibleOwnerClicked = false; private static volatile boolean backgroundClicked = false; private static final int F_X = 200, F_Y = 200, F_W = 200, F_H = 200; private static final int H_X = F_X - 10, H_Y = F_Y - 10, H_W = F_W + 20, H_H = F_H + 20; private static final int C_X = F_X + F_W / 2, C_Y = F_Y + F_H / 2; static final Color helperFrameBgColor = Color.blue; static final Color invisibleFrameBgColor = Color.green; static Frame invisibleFrame; static Frame helperFrame; static Window ownedWindow; static Robot robot; static void createUI() { /* A background frame to compare a pixel color against * It should be centered in the same location as the invisible * frame but extend beyond its bounds. */ helperFrame = new Frame("Background frame"); helperFrame.setBackground(helperFrameBgColor); helperFrame.setLocation(H_X, H_Y); helperFrame.setSize(H_W, H_H); System.out.println("Helper requested bounds : x=" + H_X + " y="+ H_Y +" w="+ H_W +" h="+ H_H); helperFrame.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent ev) { System.out.println("Background helper frame clicked"); backgroundClicked = true; } }); helperFrame.setVisible(true); /* An owner frame that should stay invisible but theoretical * bounds are within the helper frame. */ invisibleFrame = new Frame("Invisible Frame"); invisibleFrame.setBackground(invisibleFrameBgColor); invisibleFrame.setLocation(F_X, F_Y); invisibleFrame.setSize(F_W, F_H); invisibleFrame.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent ev) { System.out.println("Invisible owner clicked"); invisibleOwnerClicked = true; } }); /* An owned window of the invisible frame that is located * such that it does not overlap either the helper or * the invisisible frame. */ ownedWindow = new Window(invisibleFrame); ownedWindow.setBackground(Color.RED); ownedWindow.setLocation(H_X+H_W+100, H_Y+H_W+100); ownedWindow.setSize(100, 100); ownedWindow.setVisible(true); Toolkit.getDefaultToolkit().sync(); } static void captureScreen() throws Exception { System.out.println("Writing screen capture"); Rectangle screenRect = helperFrame.getGraphicsConfiguration().getBounds(); java.awt.image.BufferedImage bi = robot.createScreenCapture(screenRect); javax.imageio.ImageIO.write(bi, "png", new java.io.File("screen_IO.png")); } public static void main(String[] args) throws Exception { try { EventQueue.invokeAndWait(() -> createUI()); robot = new Robot(); robot.waitForIdle(); robot.setAutoDelay(100); robot.setAutoWaitForIdle(true); Rectangle helperBounds = helperFrame.getBounds(); System.out.println("helperFrame bounds = " + helperBounds); if (!helperBounds.contains(C_X, C_Y)) { System.out.println("Helper not positioned where it needs to be"); return; } // Clicking the owned window shouldn't make its owner visible Rectangle ownedWindowBounds = ownedWindow.getBounds(); robot.mouseMove(ownedWindowBounds.x + ownedWindowBounds.width / 2, ownedWindowBounds.y + ownedWindowBounds.height / 2); robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); robot.delay(1000); // 1. Check the color at the center of the invisible & helper frame location Color c = robot.getPixelColor(C_X, C_Y); System.out.println("Sampled pixel at " + C_X +"," + C_Y); System.out.println("Pixel color: " + c); if (c == null) { captureScreen(); throw new RuntimeException("Robot.getPixelColor() failed"); } if (c.equals(invisibleFrameBgColor)) { captureScreen(); throw new RuntimeException("The invisible frame has become visible"); } if (!c.equals(helperFrameBgColor)) { captureScreen(); throw new RuntimeException( "Background frame was covered by something unexpected"); } // 2. Try to click it - event should be delivered to the // helper frame, not the invisible frame. robot.mouseMove(C_X, C_Y); robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); robot.delay(1000); if (invisibleOwnerClicked) { captureScreen(); throw new RuntimeException( "The invisible owner frame got clicked. Looks like it became visible."); } if (!backgroundClicked) { captureScreen(); throw new RuntimeException( "The background helper frame hasn't been clicked"); } } finally { EventQueue.invokeAndWait(() -> { if (ownedWindow != null) ownedWindow.dispose(); if (invisibleFrame != null) invisibleFrame.dispose(); if (helperFrame != null) helperFrame.dispose(); }); } } }