From 6d6d00b69cea47ccbe05a844db0fb6c384045caa Mon Sep 17 00:00:00 2001 From: Alexander Zuev Date: Sat, 29 Apr 2023 18:19:11 +0000 Subject: [PATCH] 8306954: Open source five Focus related tests Reviewed-by: prr --- .../java/awt/Focus/AsyncUpFocusCycleTest.java | 186 +++++++++++ .../Focus/ClearMostRecentFocusOwnerTest.java | 307 ++++++++++++++++++ .../java/awt/Focus/ConsumedTabKeyTest.java | 232 +++++++++++++ .../jdk/java/awt/Focus/EventRetargetTest.java | 124 +++++++ .../ExtraPropChangeNotifVetoingTest.java | 113 +++++++ 5 files changed, 962 insertions(+) create mode 100644 test/jdk/java/awt/Focus/AsyncUpFocusCycleTest.java create mode 100644 test/jdk/java/awt/Focus/ClearMostRecentFocusOwnerTest.java create mode 100644 test/jdk/java/awt/Focus/ConsumedTabKeyTest.java create mode 100644 test/jdk/java/awt/Focus/EventRetargetTest.java create mode 100644 test/jdk/java/awt/Focus/ExtraPropChangeNotifVetoingTest.java diff --git a/test/jdk/java/awt/Focus/AsyncUpFocusCycleTest.java b/test/jdk/java/awt/Focus/AsyncUpFocusCycleTest.java new file mode 100644 index 0000000000000..d15476d3f82f0 --- /dev/null +++ b/test/jdk/java/awt/Focus/AsyncUpFocusCycleTest.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2001, 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 4394789 + @summary KeyboardFocusManager.upFocusCycle is not working for Swing properly + @key headful + @run main AsyncUpFocusCycleTest +*/ + + +import javax.swing.DefaultFocusManager; +import javax.swing.JButton; +import javax.swing.JFrame; +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.DefaultKeyboardFocusManager; +import java.awt.EventQueue; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.InputEvent; +import java.lang.reflect.InvocationTargetException; + +public class AsyncUpFocusCycleTest { + volatile boolean isFailed = true; + Object sema = new Object(); + JFrame frame; + Point location; + JButton button; + Insets insets; + int width; + + public void start() throws InterruptedException, + InvocationTargetException { + try { + Robot robot = new Robot(); + robot.mouseMove(100, 100); + + EventQueue.invokeAndWait(() -> { + frame = new JFrame("AsyncUpFocusCycleTest") { + public void requestFocus() { + boolean ret = super.requestFocus(false); + System.err.println("requestFocus() on Frame " + ret); + } + + protected boolean requestFocus(boolean temporary) { + boolean ret = super.requestFocus(temporary); + System.err.println("requestFocus(" + temporary + ") on Frame " + ret); + return ret; + } + + public boolean requestFocusInWindow() { + boolean ret = super.requestFocusInWindow(); + System.err.println("requestFocusInWindow() on Frame " + ret); + return ret; + } + + protected boolean requestFocusInWindow(boolean temporary) { + boolean ret = super.requestFocusInWindow(temporary); + System.err.println("requestFocusInWindow(" + temporary + ") on Frame " + ret); + return ret; + } + }; + + Container container1 = frame.getContentPane(); + container1.setBackground(Color.yellow); + + button = new JButton("Button") { + public void requestFocus() { + boolean ret = super.requestFocus(false); + System.err.println("requestFocus() on Button " + ret); + } + + public boolean requestFocus(boolean temporary) { + boolean ret = super.requestFocus(temporary); + System.err.println("requestFocus(" + temporary + ") on Button " + ret); + return ret; + } + + public boolean requestFocusInWindow() { + boolean ret = super.requestFocusInWindow(); + System.err.println("requestFocusInWindow() on Button " + ret); + return ret; + } + + protected boolean requestFocusInWindow(boolean temporary) { + boolean ret = super.requestFocusInWindow(temporary); + System.err.println("requestFocusInWindow(" + temporary + ") on Button " + ret); + return ret; + } + }; + button.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent fe) { + System.out.println("Button receive focus"); + frame.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent fe) { + System.out.println("Frame receive focus"); + synchronized (sema) { + isFailed = false; + sema.notifyAll(); + } + } + }); + } + }); + container1.add(new JButton("empty button"), BorderLayout.WEST); + container1.add(button, BorderLayout.EAST); + frame.setBounds(0, 0, 300, 300); + frame.setVisible(true); + }); + + robot.delay(2000); + robot.waitForIdle(); + + EventQueue.invokeAndWait(() -> { + location = frame.getLocationOnScreen(); + insets = frame.getInsets(); + width = frame.getWidth(); + }); + + robot.mouseMove(location.x + width / 2, location.y + insets.top / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + DefaultKeyboardFocusManager manager = new DefaultFocusManager(); + robot.delay(1000); + EventQueue.invokeAndWait(button::requestFocus); + robot.delay(1000); + EventQueue.invokeAndWait(() -> { + manager.upFocusCycle(button); + }); + + try { + synchronized (sema) { + sema.wait(5000); + } + + if (isFailed) { + System.out.println("Test FAILED"); + throw new RuntimeException("Test FAILED"); + } else { + System.out.println("Test PASSED"); + } + } catch (InterruptedException ie) { + throw new RuntimeException("Test was interrupted"); + } + } catch (AWTException e) { + System.out.println("Problem creating Robot."); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + AsyncUpFocusCycleTest test = new AsyncUpFocusCycleTest(); + test.start(); + } +} diff --git a/test/jdk/java/awt/Focus/ClearMostRecentFocusOwnerTest.java b/test/jdk/java/awt/Focus/ClearMostRecentFocusOwnerTest.java new file mode 100644 index 0000000000000..1c6ae11bf927c --- /dev/null +++ b/test/jdk/java/awt/Focus/ClearMostRecentFocusOwnerTest.java @@ -0,0 +1,307 @@ +/* + * 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(); + } +} diff --git a/test/jdk/java/awt/Focus/ConsumedTabKeyTest.java b/test/jdk/java/awt/Focus/ConsumedTabKeyTest.java new file mode 100644 index 0000000000000..cbff8eadd9708 --- /dev/null +++ b/test/jdk/java/awt/Focus/ConsumedTabKeyTest.java @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2003, 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 4715649 +@summary Tests that KEY_TYPED event for Tab key arrives if Tab key is not focus traversal key +@key headful +@run main ConsumedTabKeyTest +*/ + +import java.awt.AWTEvent; +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.Robot; +import java.awt.TextField; +import java.awt.Toolkit; +import java.awt.event.AWTEventListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.lang.reflect.InvocationTargetException; + +public class ConsumedTabKeyTest extends Panel { + TextField text; + Button button = new Button("none"); + Semaphore focusSema = new Semaphore(); + Semaphore releaseSema = new Semaphore(); + Semaphore buttonFocusSema = new Semaphore(); + Robot robot; + volatile boolean keyTyped; + volatile boolean hasFocus; + static Frame frame; + + public void init() { + this.setLayout(new FlowLayout()); + text = new TextField(); + + text.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent e) { + focusSema.raise(); + } + }); + button.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent e) { + buttonFocusSema.raise(); + } + }); + add(text); + add(button); + setSize(200, 200); + setVisible(true); + validate(); + Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { + public void eventDispatched(AWTEvent e) { + if (e.getID() == KeyEvent.KEY_RELEASED) { + releaseSema.raise(); + } + if (e.getID() == KeyEvent.KEY_TYPED) { + keyTyped = true; + } + } + }, InputEvent.KEY_EVENT_MASK); + try { + robot = new Robot(); + } catch (Exception re) { + throw new RuntimeException("Couldn't create Robot"); + } + } + + public void start() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (!text.isFocusOwner()) { + text.requestFocus(); + } + + text.setFocusTraversalKeysEnabled(false); + }); + + try { + focusSema.doWait(1000); + } catch (InterruptedException ie1) { + throw new RuntimeException("Interrupted"); + } + + EventQueue.invokeAndWait(() -> { + hasFocus = text.isFocusOwner(); + }); + + if (!focusSema.getState() && !hasFocus) { + throw new RuntimeException("Text didn't receive focus"); + } + + robot.keyPress(KeyEvent.VK_TAB); + robot.keyRelease(KeyEvent.VK_TAB); + try { + releaseSema.doWait(1000); + } catch (InterruptedException ie2) { + throw new RuntimeException("Interrupted"); + } + + if (!releaseSema.getState()) { + throw new RuntimeException("KEY_RELEASED hasn't arrived"); + } + + if (!keyTyped) { + throw new RuntimeException("KEY_TYPED for Tab key hasn't arrived"); + } + + EventQueue.invokeAndWait(() -> { + text.setFocusTraversalKeysEnabled(true); + }); + + releaseSema.setState(false); + robot.keyPress(KeyEvent.VK_TAB); + robot.keyRelease(KeyEvent.VK_TAB); + try { + buttonFocusSema.doWait(1000); + releaseSema.doWait(1000); + } catch (InterruptedException ie2) { + throw new RuntimeException("Interrupted"); + } + + EventQueue.invokeAndWait(() -> { + hasFocus = button.isFocusOwner(); + }); + + if (!buttonFocusSema.getState() && !hasFocus) { + throw new RuntimeException("Button hasn't received focus"); + } + keyTyped = false; + releaseSema.setState(false); + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + try { + releaseSema.doWait(1000); + } catch (InterruptedException ie2) { + throw new RuntimeException("Interrupted"); + } + + if (!releaseSema.getState()) { + throw new RuntimeException("KEY_RELEASED hasn't arrived"); + } + if (!keyTyped) { + throw new RuntimeException("KEY_TYPED for A key hasn't arrived"); + } + System.err.println("PASSED"); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + ConsumedTabKeyTest test = new ConsumedTabKeyTest(); + + try { + EventQueue.invokeAndWait(() -> { + frame = new Frame("InvocationTargetException"); + frame.setLayout(new BorderLayout()); + frame.add(test, BorderLayout.CENTER); + test.init(); + frame.setLocationRelativeTo(null); + frame.pack(); + frame.setVisible(true); + }); + test.start(); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + } +} + +class Semaphore { + boolean state = false; + int waiting = 0; + + public void doWait(int timeout) throws InterruptedException { + synchronized (this) { + if (state) return; + waiting++; + wait(timeout); + waiting--; + } + } + + public void raise() { + synchronized (this) { + state = true; + if (waiting > 0) { + notifyAll(); + } + } + } + + public boolean getState() { + synchronized (this) { + return state; + } + } + + public void setState(boolean newState) { + synchronized (this) { + state = newState; + } + } +} diff --git a/test/jdk/java/awt/Focus/EventRetargetTest.java b/test/jdk/java/awt/Focus/EventRetargetTest.java new file mode 100644 index 0000000000000..25862a2ef2fb8 --- /dev/null +++ b/test/jdk/java/awt/Focus/EventRetargetTest.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2003, 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 4846162 4626092 + @summary (Key|Window|Focus)Events should not be retargeted when dispatchEvent() is called directly. + @run main EventRetargetTest +*/ + +import java.awt.AWTEvent; +import java.awt.Component; +import java.awt.Toolkit; +import java.awt.event.AWTEventListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +public class EventRetargetTest { + boolean isKEProcessed1; + boolean isKEProcessed2; + boolean isKEProcessed3; + boolean isFEProcessed1; + boolean isFEProcessed2; + boolean isFEProcessed3; + + public void start () { + final Component comp = new Component() { + public boolean isShowing() { + return true; + } + + public boolean isVisible() { + return true; + } + + public boolean isDisplayable() { + return true; + } + + protected void processKeyEvent(KeyEvent e) { + System.err.println("processKeyEvent >> " + e); + isKEProcessed1 = true; + super.processKeyEvent(e); + } + + protected void processFocusEvent(FocusEvent e) { + System.err.println("processFocusEvent >> " + e); + isFEProcessed1 = true; + super.processFocusEvent(e); + } + }; + Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { + public void eventDispatched(AWTEvent e) { + if (e instanceof KeyEvent) { + isKEProcessed2 = (e.getSource() == comp); + } + else if (e instanceof FocusEvent) { + isFEProcessed2 = (e.getSource() == comp); + } + System.err.println("Toolkit >> " + e); + } + }, AWTEvent.KEY_EVENT_MASK | AWTEvent.FOCUS_EVENT_MASK); + + comp.addKeyListener(new KeyAdapter() { + public void keyTyped(KeyEvent e) { + isKEProcessed3 = true; + System.err.println("Listener >> " + e); + } + }); + comp.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent e) { + isFEProcessed3 = true; + System.err.println("Listener >> " + e); + } + }); + + KeyEvent ke = new KeyEvent(comp, KeyEvent.KEY_TYPED, System.currentTimeMillis(), 0, + KeyEvent.VK_UNDEFINED, 'a'); + comp.dispatchEvent(ke); + + if (!(isKEProcessed1 && isKEProcessed2 && isKEProcessed3)) { + System.err.println("(" + isKEProcessed1 + "," + isKEProcessed2 + + "," + isKEProcessed3 + ")"); + throw new RuntimeException("KeyEvent is not correctly retargeted."); + } + + FocusEvent fe = new FocusEvent(comp, FocusEvent.FOCUS_GAINED, + false, null); + comp.dispatchEvent(fe); + + if (!(isFEProcessed1 && isFEProcessed2 && isFEProcessed3)) { + System.err.println("(" + isFEProcessed1 + "," + + isFEProcessed2 + "," + isFEProcessed3 + ")"); + throw new RuntimeException("FocusEvent is not correctly retargeted."); + } + } + + public static void main(String[] args) { + EventRetargetTest test = new EventRetargetTest(); + test.start(); + } +} diff --git a/test/jdk/java/awt/Focus/ExtraPropChangeNotifVetoingTest.java b/test/jdk/java/awt/Focus/ExtraPropChangeNotifVetoingTest.java new file mode 100644 index 0000000000000..ef2ddbc53746d --- /dev/null +++ b/test/jdk/java/awt/Focus/ExtraPropChangeNotifVetoingTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2004, 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 5072554 + @summary Tests that vetoing focus doesn't generate extra PropertyChange notification. + @key headful + @run main ExtraPropChangeNotifVetoingTest +*/ + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.KeyboardFocusManager; +import java.awt.Panel; +import java.awt.Robot; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyVetoException; +import java.beans.VetoableChangeListener; +import java.lang.reflect.InvocationTargetException; + +public class ExtraPropChangeNotifVetoingTest extends Panel { + Button one = new Button("One"); + Button two = new Button("Two"); + Robot robot; + static Frame frame; + + int i = 0; + + public void init() { + try { + robot = new Robot(); + } catch (AWTException e) { + throw new RuntimeException("Error: unable to create robot", e); + } + + setLayout(new FlowLayout()); + add(one); + add(two); + + KeyboardFocusManager.getCurrentKeyboardFocusManager(). + addVetoableChangeListener("permanentFocusOwner", + new VetoableChangeListener() { + public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException { + System.out.println((i++) + ". Old=" + e.getOldValue() + ", New=" + e.getNewValue()); + + if (e.getOldValue() == e.getNewValue()) { + throw new RuntimeException("Test failed!"); + } + + if (e.getNewValue() == two) { + System.out.println("VETOING"); + throw new PropertyVetoException("vetoed", e); + } + } + }); + setVisible(true); + } + + public void start() throws InterruptedException, InvocationTargetException { + EventQueue.invokeAndWait(one::requestFocusInWindow); + robot.waitForIdle(); + robot.delay(200); + EventQueue.invokeAndWait(two::requestFocusInWindow); + robot.waitForIdle(); + robot.delay(200); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + ExtraPropChangeNotifVetoingTest test = new ExtraPropChangeNotifVetoingTest(); + try { + EventQueue.invokeAndWait(() -> { + frame = new Frame("ExtraPropChangeNotifVetoingTest"); + frame.setLayout(new BorderLayout()); + frame.add(test, BorderLayout.CENTER); + test.init(); + frame.setLocationRelativeTo(null); + frame.pack(); + frame.setVisible(true); + }); + test.start(); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + } +}