/* * Copyright (c) 2002, 2023, 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 @bug 4525962 @summary Opposite component calculated inaccurately @key headful @run main ClearMostRecentFocusOwnerTest */ import java.awt.AWTEvent; import java.awt.AWTException; import java.awt.Button; import java.awt.Component; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.Insets; import java.awt.Panel; import java.awt.Point; import java.awt.Robot; import java.awt.Toolkit; import java.awt.event.AWTEventListener; import java.awt.event.FocusEvent; import java.awt.event.InputEvent; import java.lang.reflect.InvocationTargetException; import java.util.concurrent.atomic.AtomicBoolean; public class ClearMostRecentFocusOwnerTest implements AWTEventListener { final static int ROBOT_DELAY = 50; volatile Frame firstFrame; volatile Frame secondFrame; volatile Button actionButton; volatile Button btnToRemove; volatile Button btnToHide; volatile Button btnToDisable; volatile Button btnToNonFocusable; volatile Panel pnlToHide; volatile Button btnInPanel; Robot robot; volatile Component opposite = null; volatile Component focusOwner = null; volatile Object monitor = null; public void init() throws InterruptedException, InvocationTargetException { try { robot = new Robot(); } catch (AWTException e) { throw new RuntimeException("Can not create awt-robot."); } EventQueue.invokeAndWait(() -> { firstFrame = new Frame("The First Frame"); firstFrame.setName("\"1st Frame\""); secondFrame = new Frame("The Second Frame"); secondFrame.setName("\"2nd Frame\""); pnlToHide = new Panel(); pnlToHide.setName("Panel"); actionButton = new Button("Action Button"); actionButton.setName("\"" + actionButton.getLabel() + "\""); btnToRemove = new Button("To Remove"); btnToRemove.setName("\"" + btnToRemove.getLabel() + "\""); btnToHide = new Button("ToHide"); btnToHide.setName("\"" + btnToHide.getLabel() + "\""); btnToDisable = new Button("To Disable"); btnToDisable.setName("\"" + btnToDisable.getLabel() + "\""); btnToNonFocusable = new Button("To setFocusable(false)"); btnToNonFocusable.setName("\"" + btnToNonFocusable.getLabel() + "\""); btnInPanel = new Button("Int Panel"); btnInPanel.setName("\"" + btnInPanel.getLabel() + "\""); firstFrame.add(actionButton); secondFrame.setLayout(new FlowLayout()); secondFrame.add(btnToRemove); secondFrame.add(btnToHide); secondFrame.add(btnToDisable); secondFrame.add(btnToNonFocusable); secondFrame.add(pnlToHide); pnlToHide.add(btnInPanel); firstFrame.pack(); firstFrame.setVisible(true); secondFrame.pack(); secondFrame.setLocation(0, firstFrame.getHeight() + 50); secondFrame.setVisible(true); }); } public void start() throws InterruptedException, InvocationTargetException { try { Toolkit.getDefaultToolkit(). addAWTEventListener(this, AWTEvent.FOCUS_EVENT_MASK); makeFocusOwner(btnToRemove); EventQueue.invokeAndWait(() -> { secondFrame.setVisible(false); secondFrame.remove(btnToRemove); }); makeFocusOwner(actionButton); opposite = null; EventQueue.invokeAndWait(() -> { secondFrame.setVisible(true); }); makeActiveFrame(secondFrame); if (opposite != btnToHide) { System.out.println("opposite = " + opposite); throw new RuntimeException("Test FAILED: wrong opposite after Component.remove()."); } makeFocusOwner(btnToHide); EventQueue.invokeAndWait(() -> { secondFrame.setVisible(false); btnToHide.setVisible(false); }); makeFocusOwner(actionButton); opposite = null; EventQueue.invokeAndWait(() -> { secondFrame.setVisible(true); }); makeActiveFrame(secondFrame); if (opposite != btnToDisable) { System.out.println("opposite = " + opposite); throw new RuntimeException("Test FAILED: wrong opposite after Component.setVisible(false)."); } makeFocusOwner(btnToDisable); EventQueue.invokeAndWait(() -> { secondFrame.setVisible(false); btnToDisable.setEnabled(false); }); makeFocusOwner(actionButton); opposite = null; EventQueue.invokeAndWait(() -> { secondFrame.setVisible(true); }); makeActiveFrame(secondFrame); if (opposite != btnToNonFocusable) { System.out.println("opposite = " + opposite); throw new RuntimeException("Test FAILED: wrong opposite after Component.rsetEnabled(false)."); } makeFocusOwner(btnToNonFocusable); EventQueue.invokeAndWait(() -> { secondFrame.setVisible(false); btnToNonFocusable.setFocusable(false); }); makeFocusOwner(actionButton); opposite = null; EventQueue.invokeAndWait(() -> { secondFrame.setVisible(true); }); makeActiveFrame(secondFrame); if (opposite != btnInPanel) { System.out.println("opposite = " + opposite); throw new RuntimeException("Test FAILED: wrong opposite after Component.setFocusable(false)."); } makeFocusOwner(btnInPanel); EventQueue.invokeAndWait(() -> { secondFrame.setVisible(false); pnlToHide.setVisible(false); }); makeFocusOwner(actionButton); opposite = null; EventQueue.invokeAndWait(() -> { secondFrame.setVisible(true); }); makeActiveFrame(secondFrame); if (opposite == btnInPanel) { System.out.println("opposite = " + opposite); throw new RuntimeException("Test FAILED: wrong opposite after Container.setVisible(false)."); } } finally { if (firstFrame != null) { EventQueue.invokeAndWait(firstFrame::dispose); } if (secondFrame != null) { EventQueue.invokeAndWait(secondFrame::dispose); } } } public void eventDispatched(AWTEvent event) { switch (event.getID()) { case FocusEvent.FOCUS_GAINED: if (focusOwner == ((FocusEvent) event).getComponent() && monitor != null) { synchronized (monitor) { monitor.notify(); } } break; case FocusEvent.FOCUS_LOST: opposite = ((FocusEvent) event).getOppositeComponent(); break; } System.out.println(event); } void clickOnComponent(Component comp) throws InterruptedException, InvocationTargetException { System.err.println("clickOnComopnent " + comp.getName()); robot.delay(3000); int[] point = new int[2]; EventQueue.invokeAndWait(() -> { Point origin = comp.getLocationOnScreen(); Dimension dim = comp.getSize(); point[0] = origin.x + (int) dim.getWidth() / 2; point[1] = origin.y + (int) dim.getHeight() / 2; }); robot.mouseMove(point[0], point[1]); robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); robot.delay(ROBOT_DELAY); robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); } void makeFocusOwner(Component comp) throws InterruptedException, InvocationTargetException { AtomicBoolean isOwner = new AtomicBoolean(false); EventQueue.invokeAndWait(() -> { isOwner.set(comp.isFocusOwner()); }); if (!isOwner.get()) { clickOnComponent(comp); try { EventQueue.invokeAndWait(() -> { isOwner.set(comp.isFocusOwner()); }); if (!isOwner.get()) { monitor = new Object(); focusOwner = comp; synchronized (monitor) { monitor.wait(3000); } } } catch (InterruptedException ie) { throw new RuntimeException("Test was interrupted."); } } EventQueue.invokeAndWait(() -> { isOwner.set(comp.isFocusOwner()); }); if (!isOwner.get()) { throw new RuntimeException("Test can not make " + comp.getName() + " a focus owner."); } } void makeActiveFrame(Frame frame) throws InvocationTargetException, InterruptedException { robot.delay(3000); if (!frame.isActive()) { System.err.println("frame is not active"); int[] point = new int[2]; EventQueue.invokeAndWait(() -> { Point origin = frame.getLocationOnScreen(); Insets ins = frame.getInsets(); point[0] = origin.x + frame.getWidth() / 2; point[1] = origin.y + ins.top / 2; }); robot.mouseMove(point[0], point[1]); robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); robot.delay(ROBOT_DELAY); robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); } robot.delay(3000); EventQueue.invokeAndWait(() -> { if (!frame.isActive()) { throw new RuntimeException("Test can not activate " + frame.getName() + "."); } }); } public static void main(String[] args) throws InterruptedException, InvocationTargetException { ClearMostRecentFocusOwnerTest test = new ClearMostRecentFocusOwnerTest(); test.init(); test.start(); } }